--- /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