IEBgps/src/IEFaceBrowser.cpp
changeset 3 93fff7023be8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IEBgps/src/IEFaceBrowser.cpp	Fri Oct 15 10:18:29 2010 +0900
@@ -0,0 +1,1424 @@
+/*
+* Copyright (c) 2009 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: Juha Kauppinen, Mika Hokkanen
+* 
+* Description: Photo Browser
+*
+*/
+
+// Include files
+#include <e32debug.h>
+#include <e32math.h>
+#include <exifmodify.h>
+#include <BAUTILS.H>
+#include "IEFaceBrowser.h"
+#include "IEBgpsInfo.h"
+#include "IEImageData.h"
+#include "ImagicConsts.h"
+#include "debug.h"
+#include <hal.h>
+
+// ================= MEMBER FUNCTIONS ================================ //
+CFaceBrowser* CFaceBrowser::NewLC(
+        RFs& aFileServer, 
+        MIEFaceBrowserObserver& aFaceBrowserObserver)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::NewLC ++"));
+    
+    CFaceBrowser* self = new (ELeave) CFaceBrowser(aFileServer, aFaceBrowserObserver);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    
+    DP0_IMAGIC(_L("CFaceBrowser::NewLC --"));
+    
+    return self;
+    }
+
+CFaceBrowser::CFaceBrowser(
+        RFs& aFileServer, 
+        MIEFaceBrowserObserver& aFaceBrowserObserver) :
+        iUtils(iFileServer),
+        iFileServer(aFileServer), 
+        iFaceBrowserObserver(aFaceBrowserObserver), 
+        CActive(EPriorityIdle)
+    {
+    
+    }
+
+CFaceBrowser::~CFaceBrowser()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::~CFaceBrowser ++"));
+    
+    if(iImageDecoder)
+        {
+        iImageDecoder->CancelDecoding();
+        
+        delete iImageDecoder;
+        iImageDecoder = NULL;
+        }
+    
+    if(iImageEncoder)
+        {
+        iImageEncoder->CancelEncoding();
+        
+        delete iImageEncoder;
+        iImageEncoder = NULL;
+        }
+    
+    if(iSymbianImageDecoder)
+    {
+        delete iSymbianImageDecoder;
+        iSymbianImageDecoder = NULL;   
+    }
+    
+    if(IsActive())
+        Cancel();
+    
+#ifdef IDL_BGPS
+    if(iIDLImageProcessor)
+        {
+        delete iIDLImageProcessor;
+        iIDLImageProcessor = NULL;
+        }
+#endif
+    
+    if(iInputBuffer)
+        {
+        delete iInputBuffer;
+        iInputBuffer = NULL;
+        }
+    
+    if(iOutputBuffer)
+        {
+        delete iOutputBuffer;
+        iOutputBuffer = NULL;
+        }
+    
+    if(iFaceYuvDataArray.Count() > 0)
+        {
+        TCroppedFaces croppedFace;
+        HBufC8* buffer = NULL;
+        TInt count = iFaceYuvDataArray.Count();
+        for(TInt i=0; i<count; i++)
+            {
+            croppedFace = iFaceYuvDataArray[0];
+            buffer = croppedFace.iYuvdata;
+            
+            iFaceYuvDataArray.Remove(0);
+            
+            delete buffer;
+            buffer = NULL;
+            }
+        }
+    
+    iFaceYuvDataArray.Close();
+    
+    if(iImageDataArray.Count() > 0)
+        {
+        TInt count = iImageDataArray.Count();
+        for(TInt i=0; i<count; i++)
+            iImageDataArray.Remove(0);
+        }
+
+    iImageDataArray.Close();
+    
+    iFaceCoordinates.Close();
+    if (iTempFaceCoordinates)
+        iTempFaceCoordinates->Close();
+   
+    DP0_IMAGIC(_L("CFaceBrowser::~CFaceBrowser --"));    
+    }
+
+void CFaceBrowser::ConstructL()
+    {
+    TInt error = KErrNone;
+    
+    DP0_IMAGIC(_L("CFaceBrowser::ConstructL ++"));
+    
+    CActiveScheduler::Add(this);
+    
+    iImageDecoder = CIEImageDecoder::NewL(iFileServer, *this);
+    
+    iImageEncoder = CIEImageEncoder::NewL(iFileServer, *this);
+    
+#ifdef IDLBGPS
+    iIDLImageProcessor = CIDLImageProcessing::NewL(*this);
+#endif
+    
+    iBrowsingState = EStateIdle;
+    
+    iNumberOfImages = 0;
+    iNumberOfImagesBrowsed = 0;
+    iNumberOfFacesCropped = 0;    
+    iNumberOfFaces = 0;
+    iTotalNumberOfFaces = 0;
+      
+    //RDebug::Print(_L("IDL_Engine_Create error = %d"), error);
+    
+    if(error != KErrNone)
+        User::Leave(error);
+    
+    DP0_IMAGIC(_L("CFaceBrowser::ConstructL --"));    
+    }
+
+void CFaceBrowser::RunL()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::RunL ++"));
+    
+    TInt error = KErrNone;
+    
+    switch(iBrowsingState)
+        {
+        case ECreatingBitmap:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - ECreatingBitmap"));
+            TInt error = iStatus.Int();
+            if(iSymbianImageDecoder)
+                {
+                delete iSymbianImageDecoder;
+                iSymbianImageDecoder = NULL;   
+                }
+#ifdef IDL_BGPS
+            ContinueFBAfterImageConversionL();
+#else
+            //ExecuteFaceDetectionL();
+#endif
+            }
+            break;
+        
+        case EFaceBrowsingRunning:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - EFaceBrowsingRunning"));
+            
+            TRAP(error, BrowseFacesL(iImageDataArray[iNumberOfImagesBrowsed]));
+            
+            if(error != KErrNone)
+                {
+                Cleanup();
+                iFaceBrowserObserver.FaceBrowsingError(error);
+                }                
+            }
+            break;
+        
+        case ESingleFaceBrowsingRunning:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - ESingleFaceBrowsingRunning"));
+            
+            //TRAP(error, BrowseFacesL(iImageDataArray[iSingleFaceBrowsingIndex]));
+            TRAP(error, BrowseFacesL(iCurrentImageData));
+            
+            if(error != KErrNone)
+                {
+                Cleanup();
+                iFaceBrowserObserver.FaceBrowsingError(error);
+                }                
+            }
+            break;
+
+        case EFaceBrowsingPaused:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - EFaceBrowsingPaused"));
+            }
+            break;
+            
+        case EFaceBrowsingStopped:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - EFaceBrowsingStopped"));
+            
+            Cleanup();
+            }
+            break;
+            
+        case EFaceBrowsingCompleted:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - EFaceBrowsingCompleted"));
+            
+            Cleanup();
+            iFaceBrowserObserver.FaceBrowsingComplete();
+            }
+            break;
+            
+        case ESingleFaceBrowsingComplete:
+            {
+            DP0_IMAGIC(_L("CFaceBrowser::RunL() - ESingleFaceBrowsingComplete"));
+            
+            Cleanup2();
+            iFaceBrowserObserver.FaceSingleFaceBrowsingComplete();
+            }
+            break;
+                               
+        default:
+            break;
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::RunL --"));    
+    }
+
+
+void CFaceBrowser::CheckCroppedFaceFileNames()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::CheckCroppedFaceFileNames"));
+    
+    TInt count = iFaceYuvDataArray.Count();
+    //Check that file was really cropped
+    for(TInt i=0; i<count; i++)
+        {
+        if(BaflUtils::FileExists(iFileServer, iFaceYuvDataArray[i].iFileName))
+            {
+            //do nothing
+            }
+        else
+            {
+            iFaceYuvDataArray.Remove(i);
+            }
+        //CImageData* data = new CImageData;
+        //data->iMGFilename = iFaceYuvDataArray[i].iFileName;
+        //iImageDataArray.Append(data);
+        }
+    }
+            
+
+void CFaceBrowser::DoCancel()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::DoCancel ++"));
+    
+    iImageDecoder->CancelDecoding();
+    iImageEncoder->CancelEncoding();
+    
+    DP0_IMAGIC(_L("CFaceBrowser::DoCancel --"));
+    }
+
+TInt CFaceBrowser::RunError(TInt aError)
+    {
+    DP1_IMAGIC(_L("CFaceBrowser::RunError - Error: %d"), aError);
+    return aError;
+    }
+
+void CFaceBrowser::BitmapReady(TInt /*aError*/)
+    {
+    
+    }
+
+// =============================== PUBLIC FUNCTIONS ============================== //
+
+void CFaceBrowser::StartFaceBrowsing(RArray<CImageData*> aImageDataArray)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::StartFaceBrowsing ++"));
+    
+    if(iBrowsingState != EStateIdle)
+        iFaceBrowserObserver.FaceBrowsingError(KErrInUse); // Better error code ?
+    
+    if(aImageDataArray.Count() == 0)
+        {
+        DP0_IMAGIC(_L("ImageDataArray is empty!!!!"));
+        iFaceBrowserObserver.FaceBrowsingError(KErrArgument);
+        }
+    else
+        {
+        iBrowsingState = EFaceBrowsingRunning;
+        //Take local copy of imagedata array
+        for(TInt i=0; i<aImageDataArray.Count(); i++)
+            {
+            if(!aImageDataArray[i]->iGridData.iCorrupted)
+                iImageDataArray.Append(aImageDataArray[i]);
+            }
+        
+        iNumberOfImages = iImageDataArray.Count();
+        
+        DP1_IMAGIC(_L("Number of images: %d"), iNumberOfImages);        
+        ContinueLoop();        
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::StartFaceBrowsing --"));    
+    }
+
+//void CFaceBrowser::StartSingleFaceDetection(TInt aIndex, RArray<TRect>* aImageCoordArray)
+//void CFaceBrowser::StartSingleFaceDetection(TInt aIndex, RArray<TRect>* aImageCoordArray, RArray<CImageData*> aImageDataArray)
+void CFaceBrowser::StartSingleFaceBrowsing(TInt aIndex, RArray<TRect>* aImageCoordArray, CImageData* aImageData)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::StartSingleFaceBrowsing ++"));
+    
+    iCurrentImageData = aImageData;
+    iSingleFaceBrowsingIndex = aIndex;
+    iTempFaceCoordinates = aImageCoordArray;
+    
+    if(iBrowsingState != EStateIdle)
+        iFaceBrowserObserver.FaceBrowsingError(KErrInUse); // Better error code ?
+    
+    iBrowsingState = ESingleFaceBrowsingRunning;
+    
+    /*//Take local copy of imagedata array
+    for(TInt i=0; i<aImageDataArray.Count(); i++)//TODO, copy only one array element, not all in alrray
+        {
+        if(!aImageDataArray[i]->iGridData.iCorrupted)
+            iImageDataArray.Append(aImageDataArray[i]);
+        }
+    */
+    iNumberOfImages = iImageDataArray.Count();
+  
+    DP0_IMAGIC(_L("CFaceBrowser::StartSingleFaceBrowsing --"));
+    ContinueLoop();        
+    }
+
+void CFaceBrowser::CancelFaceBrowsing()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::CancelFaceBrowsing ++"));
+    
+    Cleanup2();
+    
+    if(IsActive())
+        Cancel();
+    
+    //Cleanup();//TODO, check if this is needed
+    
+    DP0_IMAGIC(_L("CFaceBrowser::CancelFaceBrowsing ++"));
+    }
+
+TInt CFaceBrowser::FindFaces(const TFileName a512x512TNFileName, RArray<TRect>& aCordArray)
+    {
+    DP1_IMAGIC(_L("CFaceBrowser::FindFaces, a512x512TNFileName = %S ++"), &a512x512TNFileName);
+    
+    TInt error = KErrNone;
+    
+    TRAP(error, iUtils.ReadFaceCoordinatesL(a512x512TNFileName, aCordArray));
+    if(error != KErrNone) return error;
+    
+    DP0_IMAGIC(_L("CFaceBrowser::FindFaces --"));
+    
+    return error;    
+    }
+
+TInt CFaceBrowser::GetNumberOfFaces(const TFileName /*aFile*/)
+    {
+    return 0;
+    }
+
+//void CIEEngineImp::RemoveExifFaceCoordsL(const TDes& aFilename, TPoint aTlCoord, TPoint aBrCoord, TInt aFaceNumber)
+
+
+TInt CFaceBrowser::RemoveFaceCoordinate(const TFileName a512x512TNFileName, RArray<TRect>& aCordArray)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::RemoveFaceCoordinate++"));
+    
+     //Read first current make note
+     TInt makerNoteSize;
+     HBufC8* makerNote = ReadExifMakerNoteL(a512x512TNFileName, makerNoteSize);
+     
+     //Read first current maker note to new array from given file
+     //RArray<TRect> newCordArray;
+     //ReadFaceCoordinatesL(a512x512TNFileName, newCordArray);
+     
+     //Allocate buffer for coords to be removed
+     HBufC8* heapComment = HBufC8::NewL(100);
+     TPtr8 ptrCoords = heapComment->Des();
+     //Copy coords to be removed to descriptor
+     for(TInt i=0; i < aCordArray.Count(); i++)
+         {
+         ptrCoords.AppendNum(aCordArray[i].iTl.iX);
+         ptrCoords.Append(' ');
+         ptrCoords.AppendNum(aCordArray[i].iTl.iY);
+         ptrCoords.Append(' ');
+         ptrCoords.AppendNum(aCordArray[i].iBr.iX );
+         ptrCoords.Append(' ');
+         ptrCoords.AppendNum(aCordArray[i].iBr.iY);
+         ptrCoords.Trim();
+         }
+     
+     //Find coordinates from maker note
+     TPtr8 tmpPtr = makerNote->Des();
+     TInt res = tmpPtr.Find(ptrCoords);
+     
+     if(res == KErrNotFound)
+         return res;
+         
+     //Remove coordinates from maker note
+     TInt l = ptrCoords.Length();
+     tmpPtr.Delete(res, ptrCoords.Length()+1);
+     
+     //Find number of faces from maker note and update it
+     _LIT8(KNumberOfFace, "#");
+     res = tmpPtr.Find(KNumberOfFace);
+     
+     TLex8 lex(makerNote->Ptr());
+     lex.SkipAndMark(res+1);
+     TInt faceCount = 0;
+     lex.Val(faceCount);
+     
+     //Check lenght of number of faces string
+     TInt length = 0;
+     //TInt aFaceNumber = 1;
+     if(faceCount < 10)
+         length = 1;
+     else
+         length = 2;
+          
+     HBufC8* numberOfFaces = HBufC8::NewL(length);
+     TPtr8 FaceNroPtr = numberOfFaces->Des();
+     FaceNroPtr.AppendNum(faceCount-1);
+              
+     tmpPtr.Replace(res+1, length, FaceNroPtr);
+     //TPtr8 numberOfFaces;
+     
+     delete numberOfFaces;
+     //numberOfFaces.Copy();
+     
+     
+     // 1. Read JPEG image from the file to a buffer...
+     RFile file;
+     User::LeaveIfError( file.Open( iFileServer, a512x512TNFileName, EFileWrite ) );
+     CleanupClosePushL( file );
+     TInt size = 0;
+     file.Size(size);
+     HBufC8* jpegImage = HBufC8::NewL( size );
+     CleanupStack::PushL( jpegImage );
+     TPtr8 bufferDes( jpegImage->Des() );
+     User::LeaveIfError( file.Read( bufferDes ) );
+     CleanupStack::Pop( jpegImage );
+     CleanupStack::PopAndDestroy();
+     CleanupStack::PushL( jpegImage );
+     
+     file.Close();
+     
+     // 2. Instantiate Exif modifier in ECreate mode...
+     CExifModify* modify = CExifModify::NewL( jpegImage->Des(), CExifModify::EModify );
+     CleanupStack::PushL( modify );
+     
+     //3. Insert (Set) at least the mandatory Exif data.
+     //TInt descSize = 300;
+     //HBufC8* heapComment = HBufC8::NewL(descSize);
+     TPtr8 ptr = makerNote->Des();
+     
+     modify->SetMakerNoteL(ptr);
+     //modify->SetMakerNoteL(makerNote->Des());
+     
+     
+     // 4. Get the new Exif image...
+     // If zero length descriptor is given instead of jpeg->Des(), then only the
+     // Exif meta data is returned.
+     //HBufC8* newExif = modify->WriteDataL( jpegImage->Des() );
+     HBufC8* newExif;
+     TRAPD(err, newExif = modify->WriteDataL( jpegImage->Des() ));
+     
+     if(err != KErrNone)
+         {
+         TInt i=0;
+         }
+     
+     //TPtr8 tmp = newExif->Des();
+     
+     User::LeaveIfError( file.Replace( iFileServer, a512x512TNFileName, EFileWrite ) );
+     //Write Exif and jpeg image back to jpeg file
+     User::LeaveIfError(file.Write(*newExif));
+     
+     // Process the new Exif data
+     delete newExif;
+     newExif = NULL;
+     
+     // 5. Delete the modifier instance...
+     CleanupStack::PopAndDestroy( modify );
+     CleanupStack::PopAndDestroy( jpegImage );
+     
+     file.Close();
+    
+    DP0_IMAGIC(_L("CFaceBrowser::RemoveFaceCoordinate--"));
+    return KErrNone;
+    }
+
+
+//Writes face coordinates to Exif data if faces was found
+TInt CFaceBrowser::AddFaceCoordinate(const TFileName aFilename, RArray<TRect>& aCordArray)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::AddFaceCoordinate++"));
+    //Read first current maker note to new array from given file
+    RArray<TRect> newCordArray;
+    iUtils.ReadFaceCoordinatesL(aFilename, newCordArray);
+     
+    //Append existing coords to new coords array
+    for(TInt i=0; i<newCordArray.Count(); i++)
+        {
+        aCordArray.Append(newCordArray[i]);
+        }
+              
+     //Write all coords to file exif data manufactorer note
+    iUtils.WriteFaceCoordinatesL(aFilename, aCordArray);
+     
+    newCordArray.Close();
+    
+    DP0_IMAGIC(_L("CFaceBrowser::AddFaceCoordinate--"));
+
+    return KErrNone;
+    }
+
+
+HBufC8* CFaceBrowser::ReadExifMakerNoteL(const TDes &aFileName, TInt& aSize)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::ReadExifMakerNoteL++"));
+    HBufC8* makerNote;
+    
+    // 1. Read Exif image from the file to a buffer...
+    RFile file;
+    User::LeaveIfError( file.Open( iFileServer, aFileName , EFileRead ) );
+    CleanupClosePushL( file );
+    TInt size = 65536;
+        
+    HBufC8* exif = HBufC8::NewL( size );
+    CleanupStack::PushL( exif );
+    TPtr8 bufferDes( exif->Des() ); 
+    TInt err1 = file.Read( bufferDes );
+    TInt length = bufferDes.Length();
+    
+    if(length <= 0 )
+        {
+        CleanupStack::Pop( exif );
+        CleanupStack::PopAndDestroy();
+        //return NULL;
+        }
+    else
+        {
+        CleanupStack::Pop( exif );
+        CleanupStack::PopAndDestroy();
+        CleanupStack::PushL( exif );
+        
+        // 2. Instantiate Exif reader...
+        CExifRead* ExifRead;
+        TInt err = 0;
+        TRAP(err, ExifRead = CExifRead::NewL( exif->Des(),CExifRead::ENoJpeg ));//CExifRead::ENoTagChecking | CExifRead::ENoJpeg
+        
+        //HBufC8* comment = NULL;
+        if(err != KErrNone)
+            {
+            }
+        else
+            {
+            CleanupStack::PushL( ExifRead );
+        
+            // 3. Get required data from the Exif image...
+            TUint32  xRes;
+            TUint32  yRes;
+            ExifRead->GetPixelXDimension(xRes);
+            ExifRead->GetPixelYDimension(yRes);  
+                    
+            makerNote = ExifRead->GetMakerNoteL(); 
+            
+            // Delete the reader instance...
+            CleanupStack::PopAndDestroy( ExifRead );
+            }
+       
+        file.Close();
+        CleanupStack::PopAndDestroy( exif );
+        //DP0_IMAGIC(_L("CIEEngineImp::ReadExifData--"));
+        
+        if(makerNote == NULL)
+            {
+            User::Leave(KErrNotFound);
+            }
+        else
+            {
+            aSize = makerNote->Length();
+            //return (TUint8*)makerNote->Des().Ptr();
+            return makerNote;
+            }
+        //return comment->Des()->Ptr();
+        
+        }
+    DP0_IMAGIC(_L("CFaceBrowser::ReadExifMakerNoteL--"));
+    
+    return NULL;
+    }
+
+    
+// ================================ FACE BROWSING RELATED FUNCTIONS =============================== //
+
+//This is called from RunL when face browsing is started
+void CFaceBrowser::BrowseFacesL(CImageData* aImageData)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::BrowseFacesL++"));
+    
+    if(iBrowsingState != EFaceBrowsingRunning && iBrowsingState != ESingleFaceBrowsingRunning)
+        User::Leave(KErrNotSupported);
+    
+    TBool coordnatesExists = EFalse;
+    iCurrentImageData = aImageData;
+    
+    TFileName filename;
+    iCurrentImageData->GetFileName(filename, ESize512x512);
+    DP1_IMAGIC(_L("CFaceBrowser::BrowseFacesL 512x512TNFile = %S ++"), &filename);
+    
+    // 512x512 TN are supposed to be created in TN generation phase and should be present
+    if(!iCurrentImageData->IsImageReady(ESize512x512))
+        {
+        Cleanup();
+        User::Leave(KErrNotFound);
+        }        
+    else
+        {
+        iCurrentImageData->GetFileName(iCurrent512x512TNFileName, ESize512x512); //target file to write face coords
+        }
+    
+    //If coordinates exist we do not process image anymore
+    TRAPD(error, iUtils.ReadFaceCoordinatesL(iCurrent512x512TNFileName, iFaceCoordinates));
+    if (error == KErrNone)
+        {
+        if(iBrowsingState == ESingleFaceBrowsingRunning)
+            {
+            if(iBrowsingState == ESingleFaceBrowsingRunning)
+                 for(TInt i = 0; i<iFaceCoordinates.Count(); i++)
+                    iTempFaceCoordinates->Append(iFaceCoordinates[i]);
+            
+            iBrowsingState = ESingleFaceBrowsingComplete;
+            }
+        else
+            {
+            //Increment to the next image index
+            iNumberOfImagesBrowsed++;
+            //Check if we are at the end of image array
+            if(iNumberOfImagesBrowsed == iNumberOfImages)
+                {
+                iBrowsingState = EFaceBrowsingCompleted;
+                }
+            }
+        
+        //and continue to next image
+        ContinueLoop();
+        }
+    //Here we have image which has to be processed for face detection
+    else
+        {
+        iPrevBrowsingState = iBrowsingState;
+        iBrowsingState = ECreatingBitmap;
+        
+        TSize size;
+        if(aImageData->GetAspectRatio() > 1)
+            {
+            size.iWidth=320;
+            size.iHeight=320/aImageData->GetAspectRatio();
+            }
+        else
+            {
+            size.iWidth=320*aImageData->GetAspectRatio();
+            size.iHeight=320;
+            }
+        
+        if(size.iWidth%2 != 0)
+            size.iWidth++;
+        if(size.iHeight%2 != 0)
+            size.iHeight++;
+        
+        iBitmap = new (ELeave) CFbsBitmap();
+        iBitmap->Create(size, EColor16M);
+        
+        iSymbianImageDecoder = CImageDecoder::FileNewL(iFileServer, iCurrent512x512TNFileName, CImageDecoder::EPreferFastDecode);
+        iSymbianImageDecoder->Convert(&iStatus, *iBitmap, 0);
+        
+        if(!IsActive())
+            SetActive();
+        
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::BrowseFacesL --"));
+    }
+
+#ifdef IDLBGPS
+void CFaceBrowser::ContinueFBAfterImageConversionL()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::ContinueFBAfterImageConversionL ++"));
+    
+    iBrowsingState = iPrevBrowsingState;
+    
+    TSize size = iBitmap->SizeInPixels();
+    
+    //Init IDL
+    TInt value = 0;
+    InitializeL(EIDLFeatureFaceDetection, size, size, &value, ETrue);
+    
+    // Code for the previous face detection which needed YUV input
+    //TUint8* yuvArray;
+    //TInt yuvDataSize = size.iHeight * size.iWidth * 3 / 2;
+    //yuvArray = new TUint8 [yuvDataSize];
+    //
+    //ConvertRgb2Yuv(iBitmap, yuvArray, 3/*aBytesPerPixel*/, size);
+    // 
+    //iInputBuffer->Des().Copy(yuvArray, yuvDataSize);
+    
+    TInt bitmapSize = size.iHeight * size.iWidth * 3;
+    
+    // This is in the BGR order
+    iInputBuffer->Des().Copy((TUint8 *)iBitmap->DataAddress(), bitmapSize);
+    //delete yuvArray;
+#if 0
+    //just for testing --->
+    _LIT(KTestPath, "C:\\Images\\RGB2YUV.YUV");
+    TFileName temp;
+    temp.Copy(KTestPath);
+    
+    RFile file;
+    User::LeaveIfError(file.Replace(iFileServer, temp, EFileWrite));
+    TInt dataSize = iInputBuffer->Size();
+    file.Write(iInputBuffer->Des());
+    //file.Write(yuvArray);
+    file.Flush();
+    file.Close();    
+    //TODO, just for testing <---
+#endif
+
+#if 0
+    //just for testing ---> 
+    _LIT(KTestPath, "C:\\Images\\RawRGB.rgb");
+    TFileName temp;
+    temp.Copy(KTestPath);
+        
+    RFile file;
+    User::LeaveIfError(file.Replace(iFileServer, temp, EFileWrite));
+    TInt dataSize = iInputBuffer->Size();
+    file.Write(iInputBuffer->Des());
+    file.Flush();
+    file.Close();    
+    //just for testing <---
+#endif
+
+        
+    TInt error = KErrNone;
+    TRAP(error, BrowseFacesL(iCurrent512x512TNFileName, iFaceCoordinates));
+    
+    if(error != KErrNone)
+        {
+        Cleanup();
+        iFaceBrowserObserver.FaceBrowsingError(error);
+        }
+    
+#if 0
+    //only for debug
+    _LIT(KTestPath, "C:\\Images\\RGB2YUV.MBM");
+    TFileName temp;
+    temp.Copy(KTestPath);
+    iBitmap->Save(temp);
+#endif
+    
+    iBitmap->Reset();
+    delete iBitmap;
+    
+    if(iBrowsingState == ESingleFaceBrowsingRunning)
+        iBrowsingState = ESingleFaceDetectionComplete;
+    
+    ContinueLoop();
+    
+    DP0_IMAGIC(_L("CFaceBrowser::ContinueFBAfterImageConversionL --"));
+    }
+#endif
+
+//http://wiki.forum.nokia.com/index.php/TSS001195_-_RGB_to_YUV_conversion
+void CFaceBrowser::ConvertRgb2Yuv(CFbsBitmap* aSourceBitmap, TUint8* aYuv, TInt aBytesPerPixel, const TSize aSize)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::ConvertRgb2Yuv++"));
+    
+    // Definitions that help access each colour component in source bitmap
+    #define   sR ((TInt32)(s[2]))
+    #define   sG ((TInt32)(s[1]))
+    #define   sB ((TInt32)(s[0]))
+     
+    const TInt KImageNumPixels = aSize.iHeight*aSize.iWidth;
+     
+    // Lock source bitmap (CFbsBitmap)
+    aSourceBitmap->LockHeap(EFalse);
+    TUint8* s = (TUint8*)aSourceBitmap->DataAddress();
+        
+    TInt i = 0;
+    TInt ui = KImageNumPixels;
+    TInt vi = KImageNumPixels + KImageNumPixels/4;
+       
+    //iYuv is an array of TUint8 values, length (KImageNumPixels*3/2)
+         
+    for(TInt j=0; j < aSize.iHeight; j++)
+        {
+        for(TInt k=0; k < aSize.iWidth; k++)
+            {
+            // Y value is generated for each pixel
+            aYuv[i] = (TUint8)( (  66*sR + 129*sG +  25*sB + 128) >> 8 ) + 16;
+              
+            // U, V values are generated for every other pixel on every other scanline 
+            if(0 == j%2 && 0 == k%2)
+                {
+                aYuv[ui++] = (TUint8)( (-38*sR - 74*sG + 112*sB + 128) >> 8 ) + 128;
+                aYuv[vi++] = (TUint8)( (112*sR - 94*sG - 18*sB + 128) >> 8 ) + 128;
+                }
+            i++; 
+            s+=aBytesPerPixel; // Number of bytes representing one pixel in source
+                               // bitmap e.g. if bitmap display mode == EColor16M 
+                               // (24bits/pixel), then iBytesPerPixel == 3
+            }
+        }
+       
+    aSourceBitmap->UnlockHeap(EFalse);
+    // iYuv now contains the source frame converted to YUV420p format
+    
+    DP0_IMAGIC(_L("CFaceBrowser::ConvertRgb2Yuv--"));
+    }
+
+#ifdef IDLBGPS
+//This is called after YUV data has been completed
+void CFaceBrowser::BrowseFacesL(const TFileName a512x512TNFileName, RArray<TRect>& aFaceCoordinates)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::BrowseFacesL ++"));
+    
+       
+    TPtr8 inBuffer = iInputBuffer->Des();
+    TPtr8 outBuffer = iOutputBuffer->Des();
+    
+    iIDLImageProcessor->SetInOutDataL(inBuffer, outBuffer);
+    iIDLImageProcessor->ProcessImageL();
+    
+    TInt count = aFaceCoordinates.Count();
+    for(TInt i=0; i<count; i++)
+        aFaceCoordinates.Remove(0);
+    
+    GetFaceCoordinates(iNumberOfFaces, aFaceCoordinates);
+    
+    //Add number of faces to image data
+    iCurrentImageData->SetNumberOfFaces(iNumberOfFaces);
+    
+    if(iBrowsingState == ESingleFaceBrowsingRunning)
+         for(TInt i = 0; i<aFaceCoordinates.Count(); i++)
+            iTempFaceCoordinates->Append(aFaceCoordinates[i]);
+ 
+    iUtils.WriteFaceCoordinatesL(a512x512TNFileName, aFaceCoordinates);
+    
+    if(iBrowsingState == EFaceBrowsingRunning)
+        {
+        if(iBrowsingState == EFaceBrowsingRunning)
+            iNumberOfImagesBrowsed++;
+        
+        if(iNumberOfImagesBrowsed == iNumberOfImages)
+            iBrowsingState = EFaceBrowsingCompleted;
+        }
+    else if(iBrowsingState == ESingleFaceBrowsingRunning)
+        {
+        iBrowsingState = ESingleFaceDetectionComplete;
+        }
+    
+        
+    DP0_IMAGIC(_L("CFaceBrowser::BrowseFacesL --"));
+    }
+
+void CFaceBrowser::GetFaceCoordinates(TInt& aNumberOfFaces, RArray<TRect>& aCordArray)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::GetFaceCoordinates ++"));
+    
+    iIDLImageProcessor->GetFacesDetected(aNumberOfFaces);
+    
+    if(aNumberOfFaces <= 0)
+        DP0_IMAGIC(_L("No faces found!!!"));
+    else
+        {
+        DP1_IMAGIC(_L("Number of faces found: %d"), aNumberOfFaces);
+        
+        // Clean up the coordinate array
+        if(aCordArray.Count() > 0)
+            {
+            TInt count = aCordArray.Count();
+            for(TInt i=0; i<count; i++)
+                aCordArray.Remove(0);
+            }
+        
+        iIDLImageProcessor->GetFaceCoordinates(aCordArray);
+        aCordArray.SortSigned();
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::GetFaceCoordinates --"));
+    }
+#endif
+
+// =============================== FACE CROPPING RELATED FUNCTIONS ============================ //
+
+void CFaceBrowser::CropFacesL(CImageData* aImageData)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::CropFacesL ++"));
+    
+    TInt error = KErrNone;
+    iCurrentImageData = aImageData;
+    iNumberOfFacesCropped = 0;
+    
+    TFileName imageFileName;
+    aImageData->GetFileName(imageFileName, EFullSize);
+    error = MakeFacesDir(imageFileName);
+    
+    if(error != KErrNone && error != KErrAlreadyExists)
+        User::Leave(error);
+    
+    // 512x512 and 320x320 TN are supposed to be created in TN generation phase and should be present
+    if(!iCurrentImageData->IsImageReady(ESize512x512) || !iCurrentImageData->IsImageReady(EFullSize))
+        {
+        Cleanup();
+        User::Leave(KErrNotFound);
+        }        
+    else
+        {
+        iCurrentImageData->GetFileName(iCurrent512x512TNFileName, ESize512x512);
+        iCurrentImageData->GetFileName(iCurrentImageFileName, EFullSize);
+        }
+    
+    // We assume that all the images were searched for faces before face cropping started
+    // Hence not checking if face coordinates exists or n ot
+    iUtils.ReadFaceCoordinatesL(iCurrent512x512TNFileName, iFaceCoordinates);
+    
+    if(iFaceCoordinates.Count() == 0)
+        {
+        iNumberOfImagesBrowsed++;
+        
+        if(iNumberOfImagesBrowsed == iNumberOfImages)
+            iBrowsingState = EFaceCroppingCompleted;
+                
+        ContinueLoop();
+        }
+    else
+        {
+        iTotalNumberOfFaces +=  iFaceCoordinates.Count();
+        DP1_IMAGIC(_L("iTotalNumberOfFaces = %d"), iTotalNumberOfFaces);
+        
+        iImageDecoder->GetImageSizeL(iCurrentImageFileName, iSize);
+        
+        if(!CheckOddSize(iSize))
+            {
+            TInt size = iSize.iWidth * iSize.iHeight * 3 / 2;
+                    
+            PrepareInOutBuffersL(ETrue, size, EFalse, 0);
+            
+            iImageDecoder->ConvertJpeg2YuvL(iCurrentImageFileName, *iInputBuffer);
+            }
+        else
+            {
+            iNumberOfImagesBrowsed++;
+            
+            if(iNumberOfImagesBrowsed == iNumberOfImages)
+                iBrowsingState = EFaceCroppingCompleted;
+                            
+            ContinueLoop();
+            }        
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::CropFacesL --"));
+    }
+
+
+void CFaceBrowser::CropFacesL(const TFileName /*aImageFileName*/, RArray<TRect>& aFaceCoordinates)
+    {
+    DP1_IMAGIC(_L("CFaceBrowser::CropFacesL++, number of faces: %d"), aFaceCoordinates.Count());
+
+#ifdef IDLBGPS_CROP
+
+    TRect rect(0, 0, 0, 0);
+    TParse parser;
+    parser.Set(aImageFileName, NULL, NULL);
+        
+    iNumberOfImagesBrowsed++;
+    
+    // Clean the face data array
+    if(iFaceYuvDataArray.Count() > 0)
+        {
+        TCroppedFaces temp;
+        HBufC8* buffer = NULL;
+        TInt count  = iFaceYuvDataArray.Count();
+        
+        for(TInt i=0; i<count; i++)
+            {
+            temp = iFaceYuvDataArray[0];
+            
+            iFaceYuvDataArray.Remove(0);
+            
+            buffer = temp.iYuvdata;
+            
+            delete buffer;
+            buffer = NULL;
+            }
+        }
+    
+    for(TInt faceIndex=0; faceIndex<aFaceCoordinates.Count(); faceIndex++)
+        {
+        TSize tnSize;
+        TFileName thumbnailFileName;
+        
+        iCurrentImageData->GetFileName(thumbnailFileName, ESize32x32);
+        iImageDecoder->GetImageSizeL(thumbnailFileName, tnSize);
+        
+        rect = GetFaceRect(iSize, tnSize, aFaceCoordinates[faceIndex]);
+        
+        InitializeL(EIDLFeatureCrop, iSize, rect.Size(), &rect, EFalse);
+        
+        TPtr8 inBuffer = iInputBuffer->Des();
+        TPtr8 outBuffer = iOutputBuffer->Des();
+        
+        iIDLImageProcessor->SetInOutDataL(inBuffer, outBuffer);
+        iIDLImageProcessor->ProcessImageL();
+        
+        DP1_IMAGIC(_L("Face cropped: %d"), faceIndex);
+        
+        TCroppedFaces croppedFace;
+        croppedFace.iYuvdata = HBufC8::NewL(iOutputBuffer->Size());
+        croppedFace.iYuvdata->Des().Copy(iOutputBuffer->Des());
+        
+        croppedFace.iFileName.Append(parser.DriveAndPath());
+        croppedFace.iFileName.Append(KFaces);
+        croppedFace.iFileName.Append(parser.Name());
+        croppedFace.iFileName.Append(KUnderScr);
+        croppedFace.iFileName.AppendNum(faceIndex);
+        croppedFace.iFileName.Append(parser.Ext());
+        
+        croppedFace.iCroppedSize = rect.Size();        
+        
+        iFaceYuvDataArray.Append(croppedFace);
+        iCroppedFilenames->Append(croppedFace.iFileName);
+        }
+#endif
+    
+    iBrowsingState = EEncodingFaces;
+    
+    DP0_IMAGIC(_L("CFaceBrowser::CropFacesL --"));
+    }
+
+TRect CFaceBrowser::GetFaceRect(const TSize aOrgImageSize, const TSize aRelImageSize, const TRect aFaceRect)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::GetFaceRect ++"));
+
+    TRect faceRect(0, 0, 0, 0);
+    
+    faceRect.iTl = aFaceRect.iTl;
+    faceRect.iBr = aFaceRect.iBr;
+    
+    TReal width = 0;
+    TReal height = 0;
+    TReal aspectRatioX = 0;
+    TReal aspectRatioY = 0;
+    
+    //Converting the face rect to original image size
+    aspectRatioX = (TReal)aOrgImageSize.iWidth / (TReal)aRelImageSize.iWidth;
+    aspectRatioY = (TReal)aOrgImageSize.iHeight / (TReal)aRelImageSize.iHeight;
+    
+    //Make cropped rect bigger
+    //faceRect.Grow(faceRect.Width()/4, (faceRect.Height()/2));
+    faceRect.Grow(faceRect.Width()/2.5, (faceRect.Height()/1.5));
+    //And move ract bit higher
+    //faceRect.Move(0, -(faceRect.Height()/6));
+    faceRect.Move(0, -(faceRect.Height()/8));
+    
+    if(aspectRatioX != 1.0 || aspectRatioY != 1.0)
+        {
+        //Scale cropping rect size to original  
+        faceRect.iTl.iX *= aspectRatioX;
+        faceRect.iTl.iY *= aspectRatioY;
+        faceRect.iBr.iX *= aspectRatioX;
+        faceRect.iBr.iY *= aspectRatioY;
+        
+        // Check for extreme values and negative values
+        // Any invalid values will be made max valid values
+        if(faceRect.iTl.iX < 0) faceRect.iTl.iX = 0;
+        if(faceRect.iTl.iY < 0) faceRect.iTl.iY = 0;
+        if(faceRect.iTl.iX >= aOrgImageSize.iWidth) faceRect.iBr.iX = aOrgImageSize.iWidth-1;
+        if(faceRect.iTl.iY >= aOrgImageSize.iHeight) faceRect.iBr.iY = aOrgImageSize.iHeight-1;
+        if(faceRect.iBr.iX > aOrgImageSize.iWidth) faceRect.iBr.iX = aOrgImageSize.iWidth;
+        if(faceRect.iBr.iY > aOrgImageSize.iHeight) faceRect.iBr.iY = aOrgImageSize.iHeight;
+        
+        }    
+    
+    // Make sure that the width and height are divisible by 2, else encoder/decoder will give -10 error
+    TReal remainder = 0;
+    
+    Math::Mod(remainder, faceRect.Size().iWidth, 2);
+    
+    if(remainder != 0)
+        faceRect.iBr.iX--;
+    
+    Math::Mod(remainder, faceRect.Size().iHeight, 2);
+    
+    if(remainder != 0)
+        faceRect.iBr.iY--;
+
+    DP4_IMAGIC(_L("CFaceBrowser::GetFaceRect faceRect(%d, %d, %d, %d)--"), faceRect.iTl.iX, faceRect.iTl.iY, faceRect.iBr.iX, faceRect.iBr.iY);
+    
+    return faceRect;
+    }
+
+TInt CFaceBrowser::MakeFacesDir(const TFileName aImageName)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::MakeFacesDir ++"));
+    
+    TInt error = KErrNone;
+    
+    TParse parser;
+    parser.Set(aImageName, NULL, NULL);
+    
+    TFileName faceDir = parser.DriveAndPath();
+    faceDir.Append(KFaces);
+    
+    if(BaflUtils::PathExists(iFileServer, faceDir))
+        error = KErrAlreadyExists;
+    else
+        {
+        error = iFileServer.MkDir(faceDir);
+        
+        if(error == KErrNone)
+            error = iFileServer.SetAtt(faceDir, KEntryAttNormal, KEntryAttNormal);
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::MakeFacesDir --"));
+    
+    return error;
+    }
+
+void CFaceBrowser::EncodeFaceL(const TCroppedFaces aCroppedFace)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::EncodeFaceL ++"));
+    
+    HBufC8* buffer = aCroppedFace.iYuvdata;
+   
+    TFileName fileName = aCroppedFace.iFileName;
+    TSize size = aCroppedFace.iCroppedSize;
+    
+    DP1_IMAGIC(_L("Encoding Image: %S"), &fileName);
+    DP2_IMAGIC(_L("Size: %dx%d"), size.iWidth, size.iHeight);
+    
+    iImageEncoder->ConvertYuv2JpegL(fileName, *buffer, size);
+    
+    DP0_IMAGIC(_L("CFaceBrowser::EncodeFaceL --"));
+    }
+
+// =============================== COMMON FUNCTIONS ============================================== //
+
+#ifdef IDLBGPS
+void CFaceBrowser::InitializeL(const TIDLFeatures aIDLFeature, const TSize aInSize, const TSize aOutSize, TAny* aValue, TBool aInBufferCreate)
+    {
+    DP4_IMAGIC(_L("CFaceBrowser::InitializeL, aInsize = %dx%d, aOutSize = %dx%d ++"), aInSize.iWidth, aInSize.iHeight, aOutSize.iWidth, aOutSize.iHeight);
+    
+//    TInt value = 0;
+    TInt outputBufferSize = 0;
+    //TInt inputBufferSize = (aInSize.iWidth * aInSize.iHeight * 3 / 2);
+    TInt inputBufferSize = aInSize.iWidth * aInSize.iHeight * 3;
+    
+    iIDLImageProcessor->SetFeatureL(aIDLFeature, aValue);
+    //iIDLImageProcessor->InitializeFeatureL(aInSize, 
+    //                                        aOutSize, 
+    //                                        EIDLFormatYUV420, 
+    //                                        EIDLFormatYUV420);
+    iIDLImageProcessor->InitializeFeatureL(aInSize, 
+                                                aOutSize, 
+                                                EIDLFormatRGB, 
+                                                EIDLFormatRGB);
+    
+    iIDLImageProcessor->AllocateBuffersL(outputBufferSize);
+    
+    PrepareInOutBuffersL(aInBufferCreate, inputBufferSize, ETrue, outputBufferSize);
+    
+    DP0_IMAGIC(_L("CFaceBrowser::InitializeL --"));
+    }
+#endif
+
+void CFaceBrowser::PrepareInOutBuffersL(TBool aInBufferCreate, const TInt aInBufSize, TBool aOutBufferCreate, const TInt aOutBufSize)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::PrepareInOutBuffersL ++"));
+    
+    if(aInBufferCreate)
+        {
+        if(aInBufSize <= 0)
+            User::Leave(KErrArgument);
+        
+        if(iInputBuffer)
+            {
+            delete iInputBuffer;
+            iInputBuffer = NULL;
+            }
+        
+        iInputBuffer = HBufC8::NewL(aInBufSize);
+        }
+    
+    if(aOutBufferCreate)
+        {
+        if(aOutBufSize <= 0)
+            User::Leave(KErrArgument);
+        
+        if(iOutputBuffer)
+            {
+            delete iOutputBuffer;
+            iOutputBuffer = NULL;
+            }
+        
+        iOutputBuffer = HBufC8::NewL(aOutBufSize);
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::PrepareInOutBuffersL --"));
+    }
+
+TBool CFaceBrowser::CheckOddSize(const TSize aSize)
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::CheckOddSize ++"));
+    
+    TReal remainder = 0;
+    
+    Math::Mod(remainder, aSize.iWidth, 2);
+    
+    if(remainder != 0) return ETrue;
+    
+    Math::Mod(remainder, aSize.iHeight, 2);
+    
+    if(remainder != 0) return ETrue;
+    
+    DP0_IMAGIC(_L("CFaceBrowser::CheckOddSize --"));
+    
+    return EFalse;
+    }
+
+#if 0
+TFileName CFaceBrowser::MakeTNFileName(const TFileName aImageFileName, TBool a512TNFile, TBool /*a320TNFileName*/)
+    {
+    DP1_IMAGIC(_L("CFaceBrowser::Make512x512TNFileName, aImageFileName = %S ++"), &aImageFileName);
+    
+    TParse fileNameParser;
+    fileNameParser.Set(aImageFileName, NULL, NULL);
+    
+    TFileName tnFileName;
+    
+    tnFileName = fileNameParser.DriveAndPath();
+    
+    if(a512TNFile /*&& !a320TNFileName*/)
+        {
+        tnFileName.Append(K512x512TNFilePath);
+        tnFileName.Append(fileNameParser.Name());
+        tnFileName.Append(KTNExt);
+        }
+/*    if(!a512TNFile && a320TNFileName)
+        {
+        tnFileName.Append(K320TNFilePath);
+        tnFileName.Append(fileNameParser.Name());
+        tnFileName.Append(K320TNFileExt);
+        }*/
+    
+    DP1_IMAGIC(_L("CFaceBrowser::Make512x512TNFileName fileName512x512TN = %S --"), &tnFileName);
+    
+    return tnFileName;
+    }
+#endif    
+
+void CFaceBrowser::Cleanup()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::Cleanup ++"));
+    
+    if(iImageDecoder)
+            iImageDecoder->CancelDecoding();
+            
+    if(iImageEncoder)
+        iImageEncoder->CancelEncoding();
+        
+    if(iFaceCoordinates.Count() > 0)
+        {
+        TInt count = iFaceCoordinates.Count();
+        for(TInt i=0; i<count; i++)
+            iFaceCoordinates.Remove(0);
+        }
+    
+    if(iFaceYuvDataArray.Count() > 0)
+        {
+        TCroppedFaces croppedFaces;
+        HBufC8* buffer = NULL;
+        TInt count = iFaceYuvDataArray.Count();
+        
+        for(TInt i=0; i<count; i++)
+            {
+            croppedFaces = iFaceYuvDataArray[0];
+            iFaceYuvDataArray.Remove(0);
+            
+            buffer = croppedFaces.iYuvdata;
+            
+            delete buffer;
+            buffer = NULL;
+            }
+        }
+/*    
+    if(iImageDataArray.Count() > 0)
+        {
+        TInt count = iImageDataArray.Count();
+        for(TInt i=0; i<count; i++)
+            iImageDataArray.Remove(0);
+        }
+ */   
+    iNumberOfFaces = 0;
+    iNumberOfImages = 0;
+    iNumberOfImagesBrowsed = 0;
+    iNumberOfFacesCropped = 0;
+    
+    iCurrentImageData = NULL;
+    
+    iCurrentImageFileName = KEmptyString;
+    iCurrent512x512TNFileName = KEmptyString;
+    //iCurrent320x320TNFileName = KEmptyString;
+    
+    iBrowsingState = EStateIdle;
+    
+    DP0_IMAGIC(_L("CFaceBrowser::Cleanup --"));
+    }
+
+void CFaceBrowser::Cleanup2()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::Cleanup2 ++"));
+    
+    if(iImageDecoder)
+        iImageDecoder->CancelDecoding();
+        
+    if(iImageEncoder)
+        iImageEncoder->CancelEncoding();
+    
+    if(iFaceYuvDataArray.Count() > 0)
+        {
+        TCroppedFaces croppedFaces;
+        HBufC8* buffer = NULL;
+        TInt count = iFaceYuvDataArray.Count();
+        
+        for(TInt i=0; i<count; i++)
+            {
+            croppedFaces = iFaceYuvDataArray[0];
+            iFaceYuvDataArray.Remove(0);
+            
+            buffer = croppedFaces.iYuvdata;
+            
+            delete buffer;
+            buffer = NULL;
+            }
+        }
+
+    iBrowsingState = EStateIdle;
+    
+    DP0_IMAGIC(_L("CFaceBrowser::Cleanup2 --"));
+    }
+
+void CFaceBrowser::ContinueLoop()
+    {
+    DP0_IMAGIC(_L("CFaceBrowser::ContinueLoop++"));
+    
+    if(!IsActive())
+        {
+        SetActive();
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete(status, KErrNone);            
+        }
+    
+    DP0_IMAGIC(_L("CFaceBrowser::ContinueLoop--"));
+    }
+
+void CFaceBrowser::WriteFaceCoordToExif(TInt numOfFaces, RArray<TRect> faceCoordinates) {
+    //Add number of faces to image data
+    iCurrentImageData->SetNumberOfFaces(numOfFaces);
+    
+    if(iBrowsingState == ESingleFaceBrowsingRunning)
+         for(TInt i = 0; i<iFaceCoordinates.Count(); i++)
+            iTempFaceCoordinates->Append(iFaceCoordinates[i]);
+ 
+    iUtils.WriteFaceCoordinatesL(iCurrent512x512TNFileName, faceCoordinates);
+}
+
+// EOF