Common/Src/IEEngineUtils.cpp
changeset 3 93fff7023be8
equal deleted inserted replaced
2:e1e28b0273b0 3:93fff7023be8
       
     1 /*
       
     2 * Copyright (c) 2009 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: Juha Kauppinen, Mika Hokkanen
       
    13 * 
       
    14 * Description: Photo Browser
       
    15 *
       
    16 */
       
    17 
       
    18 #include <exifmodify.h>
       
    19 #include <BAUTILS.H>
       
    20 #include "IEEngineUtils.h" 
       
    21 #include "ImagicConsts.h"
       
    22 #include "debug.h"
       
    23 #include <exifread.h>
       
    24 #include <ExifUtility.h> 
       
    25 #include <ICLExif.h> 
       
    26 //#include <iclextjpegapi.h>  // For CExtJpegDecoder
       
    27 
       
    28 #define KJpegDecIVAUidValue 0x10272C10
       
    29 #define KJpegOptUidValue 0x101FF555
       
    30 
       
    31 EXPORT_C CIEEngineUtils::CIEEngineUtils(RFs& aFs)
       
    32     : iFs(aFs)
       
    33     {
       
    34     } 
       
    35 
       
    36 EXPORT_C CIEEngineUtils::~CIEEngineUtils()
       
    37     {
       
    38     }
       
    39 
       
    40 /* Generating IETNFileName with complete path */
       
    41 EXPORT_C void CIEEngineUtils::GenerateThumbnailFileName(
       
    42         TThumbSize aTNResolution,
       
    43         const TDesC& aSavedFileName, 
       
    44         TDes &aIETNFileName)
       
    45     {
       
    46     TFileName tmpName;
       
    47     TParse parser;
       
    48     switch(aTNResolution)
       
    49         {
       
    50         case ESize512x512:
       
    51             {
       
    52             parser.Set(aSavedFileName, NULL, NULL);
       
    53             tmpName = parser.DriveAndPath();//only path name
       
    54             tmpName.Append(K512x512TNFilePath);
       
    55             tmpName.Append(parser.NameAndExt());
       
    56             tmpName.Append(K512x512Ext);
       
    57             aIETNFileName.Copy(tmpName);
       
    58             break;
       
    59             }
       
    60         case ESize128x128:
       
    61            {
       
    62            parser.Set(aSavedFileName, NULL, NULL);
       
    63            tmpName = parser.DriveAndPath();//only path name
       
    64            tmpName.Append(K128x128TNFilePath);
       
    65            tmpName.Append(parser.NameAndExt());
       
    66            tmpName.Append(K128x128Ext);
       
    67            aIETNFileName.Copy(tmpName);
       
    68            break;
       
    69            }
       
    70         case ESize32x32:
       
    71            {
       
    72            parser.Set(aSavedFileName, NULL, NULL);
       
    73            tmpName = parser.DriveAndPath();//only path name
       
    74            tmpName.Append(K32x32TNFilePath);
       
    75            tmpName.Append(parser.NameAndExt());
       
    76            tmpName.Append(K32x32Ext);
       
    77            aIETNFileName.Copy(tmpName);
       
    78            break;
       
    79            }
       
    80         default:
       
    81            ASSERT(0);
       
    82            break;
       
    83         };
       
    84     }
       
    85 
       
    86 EXPORT_C void CIEEngineUtils::DeleteThumbnails(TDesC& aFileName, RFs& aFs)
       
    87     {
       
    88     TThumbSize res[] = { ESize512x512, ESize128x128, ESize32x32 };
       
    89     for (TInt i = 0;i < sizeof(res)/ sizeof(TThumbSize);i++)
       
    90         {
       
    91         TFileName thumbFileName;
       
    92         GenerateThumbnailFileName(res[i], aFileName, thumbFileName);
       
    93         BaflUtils::DeleteFile(aFs, thumbFileName);
       
    94         }    
       
    95     }
       
    96 
       
    97 /*Creating TN Folder */
       
    98 EXPORT_C TInt CIEEngineUtils::CreateTNFolder(RFs aFs, const TDesC& aTNPath)
       
    99     {
       
   100     TInt error = KErrNone;
       
   101     if( !BaflUtils::PathExists( aFs, aTNPath ) )
       
   102         {
       
   103         error = aFs.MkDirAll( aTNPath );
       
   104         error = aFs.SetAtt( aTNPath, KEntryAttHidden, NULL );
       
   105         }
       
   106    
       
   107     return error;
       
   108     }
       
   109 
       
   110 // Writes face coordinates to Exif data if faces was found
       
   111 EXPORT_C TInt CIEEngineUtils::AddFaceCoordinate(const TFileName aFilename, RArray<TRect>& aCordArray)
       
   112     {
       
   113     DP0_IMAGIC(_L("CIEEngineUtils::AddFaceCoordinate++"));
       
   114     // Read first current maker note to new array from given file
       
   115     RArray<TRect> newCordArray;
       
   116     ReadFaceCoordinatesL(aFilename, newCordArray);
       
   117      
       
   118     // Append existing coords to new coords array
       
   119     for(TInt i=0; i<newCordArray.Count(); i++)
       
   120         {
       
   121         aCordArray.Append(newCordArray[i]);
       
   122         }
       
   123               
       
   124      // Write all coords to file exif data manufactorer note
       
   125     WriteFaceCoordinatesL(aFilename, aCordArray);
       
   126      
       
   127     newCordArray.Close();
       
   128     
       
   129     DP0_IMAGIC(_L("CIEEngineUtils::AddFaceCoordinate--"));
       
   130     return KErrNone;
       
   131     }
       
   132 
       
   133 EXPORT_C HBufC8* CIEEngineUtils::ReadExifMakerNoteL(const TDes &aFileName)
       
   134     {
       
   135     DP0_IMAGIC(_L("CIEEngineUtils::ReadExifMakerNoteL++"));
       
   136     
       
   137     HBufC8* exif = ReadExifHeaderL(iFs, aFileName);
       
   138     CleanupStack::PushL( exif );
       
   139     
       
   140     CExifRead* exifRead = CExifRead::NewL(exif->Des(), CExifRead::ENoJpeg);
       
   141     CleanupStack::PushL( exifRead );
       
   142         
       
   143     // Get required data from the Exif image...
       
   144     /*TUint32  xRes;
       
   145     TUint32  yRes;
       
   146     exifRead->GetPixelXDimension(xRes);
       
   147     exifRead->GetPixelYDimension(yRes);*/  
       
   148     HBufC8* makerNote = exifRead->GetMakerNoteL();
       
   149     CleanupStack::PushL( makerNote );
       
   150             
       
   151     CleanupStack::Pop( makerNote );
       
   152     CleanupStack::PopAndDestroy( exifRead );
       
   153     CleanupStack::PopAndDestroy( exif );
       
   154 
       
   155     DP0_IMAGIC(_L("CIEEngineUtils::ReadExifMakerNoteL--"));
       
   156     return makerNote;
       
   157     }
       
   158 
       
   159 EXPORT_C TInt CIEEngineUtils::RemoveFaceCoordinate(const TFileName a128x128TNFileName, RArray<TRect>& aCordArray)
       
   160     {
       
   161     DP0_IMAGIC(_L("CIEEngineUtils::RemoveFaceCoordinate++"));
       
   162     
       
   163     //Read first current make note
       
   164     HBufC8* makerNote = ReadExifMakerNoteL(a128x128TNFileName);
       
   165      
       
   166     // Allocate buffer for coords to be removed
       
   167     HBufC8* heapComment = HBufC8::NewL(100);
       
   168     TPtr8 ptrCoords = heapComment->Des();
       
   169     //Copy coords to be removed to descriptor
       
   170     for(TInt i=0; i < aCordArray.Count(); i++)
       
   171         {
       
   172         ptrCoords.AppendNum(aCordArray[i].iTl.iX);
       
   173         ptrCoords.Append(' ');
       
   174         ptrCoords.AppendNum(aCordArray[i].iTl.iY);
       
   175         ptrCoords.Append(' ');
       
   176         ptrCoords.AppendNum(aCordArray[i].iBr.iX );
       
   177         ptrCoords.Append(' ');
       
   178         ptrCoords.AppendNum(aCordArray[i].iBr.iY);
       
   179         ptrCoords.Trim();
       
   180         }
       
   181      
       
   182     //Find coordinates from maker note
       
   183     TPtr8 tmpPtr = makerNote->Des();
       
   184     TInt res = tmpPtr.Find(ptrCoords);
       
   185      
       
   186     if(res == KErrNotFound)
       
   187         return res;
       
   188          
       
   189     //Remove coordinates from maker note
       
   190     TInt l = ptrCoords.Length();
       
   191     tmpPtr.Delete(res, ptrCoords.Length()+1);
       
   192      
       
   193     //Find number of faces from maker note and update it
       
   194     _LIT8(KNumberOfFace, "#");
       
   195     res = tmpPtr.Find(KNumberOfFace);
       
   196      
       
   197     TLex8 lex(makerNote->Ptr());
       
   198     lex.SkipAndMark(res+1);
       
   199     TInt faceCount = 0;
       
   200     lex.Val(faceCount);
       
   201      
       
   202     //Check lenght of number of faces string
       
   203     TInt length = 0;
       
   204     //TInt aFaceNumber = 1;
       
   205     if(faceCount < 10)
       
   206         length = 1;
       
   207     else
       
   208         length = 2;
       
   209           
       
   210     HBufC8* numberOfFaces = HBufC8::NewL(length);
       
   211     TPtr8 FaceNroPtr = numberOfFaces->Des();
       
   212     FaceNroPtr.AppendNum(faceCount-1);
       
   213               
       
   214     tmpPtr.Replace(res+1, length, FaceNroPtr);
       
   215     //TPtr8 numberOfFaces;
       
   216      
       
   217     delete numberOfFaces;
       
   218     //numberOfFaces.Copy();
       
   219     
       
   220     // 1. Read JPEG image from the file to a buffer...
       
   221     RFile file;
       
   222     User::LeaveIfError( file.Open( iFs, a128x128TNFileName, EFileWrite ) );
       
   223     CleanupClosePushL( file );
       
   224     TInt size = 0;
       
   225     file.Size(size);
       
   226     HBufC8* jpegImage = HBufC8::NewL( size );
       
   227     CleanupStack::PushL( jpegImage );
       
   228     TPtr8 bufferDes( jpegImage->Des() );
       
   229     User::LeaveIfError( file.Read( bufferDes ) );
       
   230     CleanupStack::Pop( jpegImage );
       
   231     CleanupStack::PopAndDestroy();
       
   232     CleanupStack::PushL( jpegImage );
       
   233      
       
   234     file.Close();
       
   235      
       
   236     // 2. Instantiate Exif modifier in ECreate mode...
       
   237     CExifModify* modify = CExifModify::NewL( jpegImage->Des(), CExifModify::EModify );
       
   238     CleanupStack::PushL( modify );
       
   239      
       
   240     //3. Insert (Set) at least the mandatory Exif data.
       
   241     //TInt descSize = 300;
       
   242     //HBufC8* heapComment = HBufC8::NewL(descSize);
       
   243     TPtr8 ptr = makerNote->Des();
       
   244      
       
   245     modify->SetMakerNoteL(ptr);
       
   246     //modify->SetMakerNoteL(makerNote->Des());
       
   247      
       
   248     // 4. Get the new Exif image...
       
   249     // If zero length descriptor is given instead of jpeg->Des(), then only the
       
   250     // Exif meta data is returned.
       
   251     //HBufC8* newExif = modify->WriteDataL( jpegImage->Des() );
       
   252     HBufC8* newExif;
       
   253     TRAPD(err, newExif = modify->WriteDataL( jpegImage->Des() ));
       
   254      
       
   255     if(err != KErrNone)
       
   256         {
       
   257         TInt i=0;
       
   258         }
       
   259      
       
   260     //TPtr8 tmp = newExif->Des();
       
   261      
       
   262     User::LeaveIfError( file.Replace( iFs, a128x128TNFileName, EFileWrite ) );
       
   263     //Write Exif and jpeg image back to jpeg file
       
   264     User::LeaveIfError(file.Write(*newExif));
       
   265      
       
   266     // Process the new Exif data
       
   267     delete newExif;
       
   268     newExif = NULL;
       
   269      
       
   270     // 5. Delete the modifier instance...
       
   271     CleanupStack::PopAndDestroy( modify );
       
   272     CleanupStack::PopAndDestroy( jpegImage );
       
   273      
       
   274     file.Close();
       
   275     
       
   276     DP0_IMAGIC(_L("CIEEngineUtils::RemoveFaceCoordinate--"));
       
   277     return KErrNone;
       
   278     }
       
   279 
       
   280 
       
   281 
       
   282 EXPORT_C void CIEEngineUtils::WriteFaceCoordinatesL(const TFileName a512x512TNFileName, RArray<TRect>& aCordArray)
       
   283     {
       
   284     DP1_IMAGIC(_L("CIEEngineUtils::WriteFaceCoordinatesL a512x512TNFileName = %S ++"), &a512x512TNFileName);
       
   285     
       
   286     TInt error = KErrNone;
       
   287     RFile tnFile;
       
   288     TInt size = 0;
       
   289     
       
   290     //Check that coords got from IDL makes sense. Eg. not out of image area etc.
       
   291     /*TSize tnSize;
       
   292     iImageDecoder->GetImageSizeL(iCurrentImageData->iMGTN_320x320_Filename, tnSize);
       
   293     TInt brx;
       
   294     
       
   295     TInt count = aCordArray.Count();
       
   296     TBool removed = EFalse;
       
   297     for(TInt i=0; i<count; i++)
       
   298         {
       
   299         brx = aCordArray[i].iBr.iX;
       
   300         brx = aCordArray[i].iBr.iY;
       
   301         brx = aCordArray[i].iTl.iX;
       
   302         brx = aCordArray[i].iTl.iY;
       
   303         if(aCordArray[i].iTl.iX >= aCordArray[i].iBr.iX || aCordArray[i].iTl.iY >= aCordArray[i].iBr.iY)
       
   304             {
       
   305             aCordArray.Remove(i);
       
   306             removed = ETrue;
       
   307             }
       
   308         if(removed)
       
   309             count = aCordArray.Count();
       
   310         }
       
   311     */
       
   312    
       
   313     User::LeaveIfError(tnFile.Open(iFs, a512x512TNFileName, EFileRead));
       
   314     
       
   315     tnFile.Size(size);
       
   316     
       
   317     if(size <= 0) User::Leave(KErrUnderflow); // May be more meaningful error code shud be returned
       
   318     
       
   319     HBufC8* imageData = HBufC8::NewL(size);
       
   320     
       
   321     CleanupStack::PushL(imageData);
       
   322     
       
   323     TPtr8 imageDataPtr = imageData->Des();
       
   324     
       
   325     User::LeaveIfError(tnFile.Read(imageDataPtr));
       
   326     
       
   327     tnFile.Close();
       
   328     
       
   329     // Create the exifmodifier instance
       
   330     CExifModify* exifModifier = CExifModify::NewL(imageDataPtr, CExifModify::ECreate);
       
   331     
       
   332     CleanupStack::PushL(exifModifier);
       
   333     
       
   334     //3. Insert (Set) at least the mandatory Exif data...
       
   335     exifModifier->SetXResolutionL( 123, 1 ); 
       
   336     exifModifier->SetYResolutionL( 512, 1 ); 
       
   337     exifModifier->SetResolutionUnitL( 2 );
       
   338     exifModifier->SetYCbCrPositioningL( 1 );
       
   339     exifModifier->SetComponentsConfigurationL( 1, 2, 3, 0 );
       
   340     exifModifier->SetColorSpaceL( 1 );
       
   341     exifModifier->SetPixelXDimensionL( 512 );
       
   342     exifModifier->SetPixelYDimensionL( 512 );
       
   343     
       
   344     TInt descSize = aCordArray.Count()*4*4 + 32+10; // Be careful calculating like this!!!
       
   345     
       
   346     HBufC8* heapComment = HBufC8::NewL(descSize);
       
   347     
       
   348     CleanupStack::PushL(heapComment);
       
   349     
       
   350     TPtr8 ptr = heapComment->Des();
       
   351      
       
   352     ptr.Append(KFaceCoordsHeader);
       
   353     ptr.Append(KSpace);
       
   354     ptr.Append(KFaceCoordsImagicVersion);
       
   355     ptr.Append(KSpace);
       
   356     ptr.Append(KHash);
       
   357      
       
   358     //Set number of faces detected to Exif data
       
   359     if(aCordArray.Count() == 0)
       
   360         ptr.Append(KZero);
       
   361     else
       
   362         {
       
   363         ptr.AppendNum(aCordArray.Count());
       
   364         ptr.Append(KSpace);
       
   365         for(TInt i=0; i<aCordArray.Count(); i++)
       
   366             {
       
   367             //TInt size = ptr.Size();
       
   368             ptr.AppendNum(aCordArray[i].iTl.iX);
       
   369             ptr.Append(KSpace);
       
   370             ptr.AppendNum(aCordArray[i].iTl.iY);
       
   371             ptr.Append(KSpace);
       
   372             ptr.AppendNum(aCordArray[i].iBr.iX);
       
   373             ptr.Append(KSpace);
       
   374             ptr.AppendNum(aCordArray[i].iBr.iY);
       
   375             ptr.Append(KSpace);
       
   376             }    
       
   377         }
       
   378     
       
   379     exifModifier->SetMakerNoteL(ptr);
       
   380     
       
   381     HBufC8* newImageData = exifModifier->WriteDataL(imageDataPtr); // newImageData contains the image data with the modified exif data
       
   382     CleanupStack::PushL(newImageData);
       
   383     
       
   384     if(newImageData == NULL)
       
   385         User::Leave(KErrNotFound); // Better error code should be returned
       
   386     
       
   387     TPtr8 newImageDataPtr = newImageData->Des();
       
   388     
       
   389     // Create the new thumbnail image with modified exif data
       
   390     User::LeaveIfError(tnFile.Replace(iFs, a512x512TNFileName, EFileWrite));
       
   391     User::LeaveIfError(tnFile.Write(newImageDataPtr));
       
   392     
       
   393     tnFile.Flush();
       
   394     tnFile.Close();
       
   395     
       
   396     CleanupStack::PopAndDestroy(4);
       
   397     
       
   398     DP0_IMAGIC(_L("CIEEngineUtils::WriteFaceCoordinatesL --"));
       
   399     }
       
   400 
       
   401 EXPORT_C void CIEEngineUtils::ReadFaceCoordinatesL(const TFileName a512x512TNFileName, RArray<TRect>& aCordArray)
       
   402     {
       
   403     DP1_IMAGIC(_L("CIEEngineUtils::ReadFaceCoordinatesL, a512x512TNFileName = %S ++"), &a512x512TNFileName);
       
   404     
       
   405     TInt count = aCordArray.Count();
       
   406     for(TInt i=0; i<count; i++)
       
   407         aCordArray.Remove(0);
       
   408     
       
   409     HBufC8* imageData = ReadExifHeaderL(iFs, a512x512TNFileName);
       
   410     CleanupStack::PushL(imageData);
       
   411 
       
   412     CExifRead* exifReader;
       
   413     exifReader = CExifRead::NewL(imageData->Des(), CExifRead::ENoJpeg);
       
   414     CleanupStack::PushL(exifReader);
       
   415     
       
   416     HBufC8* makerNoteData = exifReader->GetMakerNoteL();
       
   417     TPtr8 makerNoteDataPtr = makerNoteData->Des();
       
   418 
       
   419     // No valid face information
       
   420     if (makerNoteDataPtr.Find(KFaceCoordsHeader) != 0)
       
   421         User::Leave(KErrNotFound);
       
   422     
       
   423     // 31 is the length of the string KFaceCoordsHeader+KSpace+KFaceCoordsImagicVersion+KSpace+KHash
       
   424     makerNoteDataPtr.Delete(0, 31);
       
   425 
       
   426     TRect rect(0,0,0,0);
       
   427     TLex8 lex(makerNoteDataPtr.Ptr());
       
   428     TInt faceCount = 0;
       
   429     
       
   430     lex.Val(faceCount);
       
   431     
       
   432     if(faceCount > 0)
       
   433         {
       
   434         for(TInt i=0; i<faceCount; i++)
       
   435             {
       
   436             lex.SkipSpaceAndMark(); 
       
   437             lex.Val(rect.iTl.iX);
       
   438             lex.SkipSpaceAndMark(); 
       
   439             lex.Val(rect.iTl.iY);
       
   440             
       
   441             lex.SkipSpaceAndMark(); 
       
   442             lex.Val(rect.iBr.iX);
       
   443             lex.SkipSpaceAndMark(); 
       
   444             lex.Val(rect.iBr.iY);
       
   445             
       
   446             aCordArray.Append(rect);
       
   447             
       
   448             DP4_IMAGIC(_L("Rect(%d, %d, %d, %d)"), rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY);
       
   449             
       
   450             rect = TRect(0,0,0,0);
       
   451             }
       
   452         aCordArray.SortSigned();
       
   453         }
       
   454     
       
   455     CleanupStack::PopAndDestroy(2);
       
   456         
       
   457     DP0_IMAGIC(_L("CIEEngineUtils::ReadFaceCoordinatesL --"));
       
   458     }
       
   459 
       
   460 EXPORT_C void CIEEngineUtils::GetModifiedTimeL(const TDes &aFileName, TTime& aTime)
       
   461     {
       
   462     DP0_IMAGIC(_L("CIEEngineUtils::GetFileModifiedTimeL++"));
       
   463    
       
   464     // Read file modified date
       
   465     RFile file;
       
   466     TInt error = file.Open(iFs, aFileName , EFileRead);
       
   467     DP1_IMAGIC(_L("CIEEngineUtils::GetFileModifiedTimeL - file open error = %d"), error);
       
   468     User::LeaveIfError(error);
       
   469     file.Modified(aTime);
       
   470     file.Close();
       
   471     DP0_IMAGIC(_L("CIEEngineUtils::GetFileModifiedTimeL--"));
       
   472     }
       
   473 
       
   474 EXPORT_C void CIEEngineUtils::GetImageSizeL(const TDes &aFileName, TSize& aSize)
       
   475     {
       
   476     DP0_IMAGIC(_L("CIEEngineUtils::GetImageSizeL++"));
       
   477     
       
   478     CImageDecoder* imageDecoder = CImageDecoder::FileNewL(iFs, aFileName);
       
   479     TFrameInfo frameInfo = imageDecoder->FrameInfo();
       
   480     aSize = frameInfo.iFrameCoordsInPixels.Size();
       
   481 
       
   482     delete imageDecoder;
       
   483     imageDecoder = NULL;   
       
   484     
       
   485     DP2_IMAGIC(_L("CIEEngineUtils::GetImageSizeL-- [%d x %d]"), aSize.iWidth, aSize.iHeight);
       
   486     }
       
   487 
       
   488 EXPORT_C HBufC8* CIEEngineUtils::ReadExifHeaderL(RFs& aFs, const TDesC &aFileName) 
       
   489     {
       
   490     DP0_IMAGIC(_L("CIEEngineUtils::ReadExifHeaderL++"));
       
   491     RFile file;
       
   492     User::LeaveIfError(file.Open(aFs, aFileName, EFileRead|EFileShareReadersOnly));
       
   493     CleanupClosePushL(file);
       
   494     
       
   495     TInt size;
       
   496     file.Size(size);
       
   497     size = Min(size, 64 * 1024);    // TODO use exact exif size
       
   498         
       
   499     HBufC8* exif = HBufC8::NewL(size);
       
   500     CleanupStack::PushL(exif);
       
   501     TPtr8 bufferPtr(exif->Des()); 
       
   502     User::LeaveIfError(file.Read(bufferPtr));
       
   503 
       
   504     CleanupStack::Pop(exif); // exif
       
   505     CleanupStack::PopAndDestroy(); // file
       
   506     
       
   507     DP0_IMAGIC(_L("CIEEngineUtils::ReadExifHeaderL--"));
       
   508     return exif;
       
   509     }
       
   510 
       
   511 EXPORT_C HBufC8* CIEEngineUtils::ReadExifThumbnailL(RFs& aFs, const TDesC& aFileName)
       
   512     {
       
   513     DP1_IMAGIC(_L("CIEEngineUtils::ReadExifThumbnailL++ %S"), &aFileName);
       
   514     
       
   515     HBufC8* exif = ReadExifHeaderL(aFs, aFileName);
       
   516     CleanupStack::PushL(exif);
       
   517     
       
   518     // Instantiate Exif reader
       
   519     CExifRead* exifRead = CExifRead::NewL(*exif, CExifRead::ENoJpeg);
       
   520     CleanupStack::PushL(exifRead);
       
   521     
       
   522     // Get required data from the Exif image
       
   523     HBufC8* exifThumb = exifRead->GetThumbnailL();
       
   524     CleanupStack::PushL(exifThumb);
       
   525 
       
   526     /*TUint32 w, w2, h, h2;
       
   527     exifRead->GetThumbnailXResolution(w, w2);
       
   528     exifRead->GetThumbnailYResolution(h, h2);*/
       
   529     
       
   530     CleanupStack::Pop(exifThumb);
       
   531     CleanupStack::PopAndDestroy(exifRead);
       
   532     CleanupStack::PopAndDestroy(exif);
       
   533     DP0_IMAGIC(_L("CIEEngineUtils::ReadExifThumbnailL--"));
       
   534     return exifThumb;
       
   535     }
       
   536 
       
   537 //------------------------------------------------------------------------------
       
   538 // Read the JPEG EXIF creation timestamp and orientation
       
   539 //------------------------------------------------------------------------------
       
   540 EXPORT_C void CIEEngineUtils::GetExifDateTimeAndOrientationL(
       
   541         const TDesC& aFilename, 
       
   542         TTime& aExifDateTime,
       
   543         TUint16& aOrientation)
       
   544     {
       
   545     HBufC8* exifDateTime = NULL;
       
   546     
       
   547 //#define USE_EXIF_DECODER
       
   548 #ifdef USE_EXIF_DECODER
       
   549     // First create the decoder and attach it to the JPEG file. The
       
   550     // decoder implementation UID has to be specified or calling
       
   551     // ExifMetadata() will crash.
       
   552     CImageDecoder* imageDecoder = NULL;
       
   553     imageDecoder = CImageDecoder::FileNewL(
       
   554             iFs, 
       
   555             aFilename, 
       
   556             CImageDecoder::EOptionNone, 
       
   557             KImageTypeJPGUid, 
       
   558             KNullUid,
       
   559             TUid::Uid(KJPGDecoderImplementationUidValue));
       
   560 
       
   561     // The specific implementation UID makes the downcasting safe.
       
   562     // Besides, there is no other way to use the decoder.
       
   563     CJPEGExifDecoder* jpegDecoder = static_cast<CJPEGExifDecoder*>(imageDecoder);
       
   564     CleanupStack::PushL(jpegDecoder);
       
   565     // Read the EXIF timestamp, format "YYYY:MM:DD HH:MM:SS".
       
   566     MExifMetadata* exifData = jpegDecoder->ExifMetadata();
       
   567     if(!exifData)
       
   568         User::Leave(KErrNotSupported);
       
   569     
       
   570     TExifReaderUtility reader(exifData);
       
   571     exifDateTime = HBufC8::NewLC(KPMMExifDateTimeOriginalLength);
       
   572     TInt error = reader.GetDateTimeOriginal(exifDateTime);
       
   573     User::LeaveIfError(error);
       
   574 #else
       
   575     HBufC8* exifData = ReadExifHeaderL(iFs, aFilename);
       
   576     CleanupStack::PushL(exifData);
       
   577     CExifRead* exifReader = CExifRead::NewL(*exifData, CExifRead::ENoJpeg);
       
   578     CleanupStack::PushL(exifReader);
       
   579     
       
   580     exifDateTime = exifReader->GetDateTimeOriginalL();
       
   581 #endif    
       
   582     // Convert the descriptor to a TDateTime as it cannot be converted
       
   583     // directly to a TTime.
       
   584     TLex8 lexer(*exifDateTime);
       
   585     TInt timeValue;
       
   586     TDateTime intermediateDateTime;
       
   587     // Year
       
   588     User::LeaveIfError(lexer.Val(timeValue));
       
   589     intermediateDateTime.SetYear(timeValue);
       
   590     lexer.Inc(); // Skip the colon.
       
   591     // Month
       
   592     User::LeaveIfError(lexer.Val(timeValue));
       
   593     intermediateDateTime.SetMonth(TMonth(timeValue-1));
       
   594     lexer.Inc();
       
   595     // Day
       
   596     User::LeaveIfError(lexer.Val(timeValue));
       
   597     intermediateDateTime.SetDay(timeValue-1);
       
   598     lexer.Inc();
       
   599     // Hours
       
   600     User::LeaveIfError(lexer.Val(timeValue));
       
   601     intermediateDateTime.SetHour(timeValue);
       
   602     lexer.Inc();
       
   603     // Minutes
       
   604     User::LeaveIfError(lexer.Val(timeValue));
       
   605     intermediateDateTime.SetMinute(timeValue);
       
   606     lexer.Inc();
       
   607     // Seconds
       
   608     User::LeaveIfError(lexer.Val(timeValue));
       
   609     intermediateDateTime.SetSecond(timeValue);
       
   610 
       
   611     // Finally, convert the TDateTime to a TTime.
       
   612     aExifDateTime = intermediateDateTime;
       
   613 
       
   614     // Read orientation
       
   615     TUint16 exifOrientation;
       
   616 #ifdef USE_EXIF_DECODER    
       
   617     if (reader.GetOrientation(exifOrientation) == KErrNone)
       
   618 #else
       
   619     if (exifReader->GetOrientation(exifOrientation) == KErrNone)
       
   620 #endif        
       
   621         {
       
   622         switch (exifOrientation)
       
   623             {
       
   624             case 1: case 2:
       
   625                 aOrientation = 0;
       
   626                 break;
       
   627 
       
   628             case 3: case 4:
       
   629                 aOrientation = 180;
       
   630                 break;
       
   631                 
       
   632             case 5: case 8:
       
   633                 aOrientation = 90;
       
   634                 break;
       
   635                 
       
   636             case 6: case 7:
       
   637                 aOrientation = 270;
       
   638                 break;
       
   639                 
       
   640             default:
       
   641                 DP0_IMAGIC(_L("CIEEngineUtils::GetExifDateTimeAndOrientationL: invalid orientation"));
       
   642             }
       
   643         
       
   644         DP1_IMAGIC(_L("CIEEngineUtils::GetExifDateTimeAndOrientationL: %d"), aOrientation);        
       
   645         }
       
   646     
       
   647 #ifdef USE_EXIF_DECODER
       
   648     CleanupStack::PopAndDestroy(exifDateTime);    
       
   649     CleanupStack::PopAndDestroy(jpegDecoder);
       
   650 #else
       
   651     CleanupStack::PopAndDestroy(exifReader);
       
   652     CleanupStack::PopAndDestroy(exifData);    
       
   653 #endif    
       
   654     }
       
   655 
       
   656 EXPORT_C TUid CIEEngineUtils::GetImageDecoderUid()
       
   657     {
       
   658     CImplementationInformationType* type;
       
   659     TInt error;
       
   660 
       
   661     TUid uid = TUid::Uid(KJpegDecIVAUidValue);
       
   662     TRAP(error, type = CImageDecoder::GetImplementationInformationL(uid));
       
   663     if (error == KErrNone)
       
   664         {
       
   665         DP0_IMAGIC(_L("CIEEngineUtils::GetImageDecoderUid: IVA decoder found"));
       
   666         return uid;
       
   667         }
       
   668 
       
   669     uid = TUid::Uid(KJpegOptUidValue);
       
   670     TRAP(error, type = CImageDecoder::GetImplementationInformationL(uid));
       
   671     if (error == KErrNone)
       
   672         {
       
   673         DP0_IMAGIC(_L("CIEEngineUtils::GetImageDecoderUid: Emuzed decoder found"));
       
   674         return uid;
       
   675         }
       
   676    
       
   677     /*CExtJpegDecoder* extDecoder;
       
   678     TRAP(error, extDecoder = CImageDecoder::DataNewL(CExtJpegDecoder::EHwImplementation));
       
   679     if (error == KErrNone)
       
   680         return extDecoder->ImplementationUid();*/
       
   681     
       
   682     /*TRAP(error, type = CImageDecoder::GetImplementationInformationL(CExtJpegDecoder::ESwImplementation));
       
   683     if (error == KErrNone)
       
   684         return type->ImplementationUid();*/ 
       
   685   
       
   686     DP0_IMAGIC(_L("CIEEngineUtils::GetImageDecoderUid: no specified decoder found"));    
       
   687     return KNullUid;
       
   688     }