imagehandlingutilities/thumbnailmanager/plugins/image/src/thumbnailimagedecoder.cpp
changeset 0 2014ca87e772
child 5 82749d516180
equal deleted inserted replaced
-1:000000000000 0:2014ca87e772
       
     1 /*
       
     2 * Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Image thumbnail decoder
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 //INCLUDE FILES
       
    21 #include <e32base.h>
       
    22 #include <imageconversion.h>
       
    23 #include <exifread.h>
       
    24 #include <e32math.h>
       
    25 
       
    26 #include <iclextjpegapi.h>
       
    27 #include "thumbnailimagedecoder.h"
       
    28 #include "thumbnaillog.h"
       
    29 #include "thumbnailpanic.h"
       
    30 
       
    31 const TUid KImageTypeSVGUid = 
       
    32     {
       
    33     0x102073E7
       
    34 };
       
    35 
       
    36 // CImageDecoder supports up to 1/8 size reduction if EFullyScaleable is
       
    37 // not set.
       
    38 const TInt KMaximumReductionFactor = 8;
       
    39 
       
    40 // Matchers for recognizing JPEG files
       
    41 _LIT( KJpegMime, "image/jpeg" );
       
    42 
       
    43 // Matcher for recognizing SVG files
       
    44 _LIT( KSvgMime, "image/svg+xml" );
       
    45 
       
    46 
       
    47 
       
    48 // ============================ MEMBER FUNCTIONS ===============================
       
    49 
       
    50 // ---------------------------------------------------------------------------
       
    51 // CThumbnailImageDecoder::CThumbnailImageDecoder()
       
    52 // C++ default constructor can NOT contain any code, that might leave.
       
    53 // ---------------------------------------------------------------------------
       
    54 //
       
    55 CThumbnailImageDecoder::CThumbnailImageDecoder( RFs& aFs ): CActive(
       
    56     EPriorityStandard ), iFs( aFs )
       
    57     {
       
    58     CActiveScheduler::Add( this );
       
    59     }
       
    60 
       
    61 
       
    62 // ---------------------------------------------------------------------------
       
    63 // CThumbnailImageDecoder::~CThumbnailImageDecoder()
       
    64 // Destructor.
       
    65 // ---------------------------------------------------------------------------
       
    66 //
       
    67 CThumbnailImageDecoder::~CThumbnailImageDecoder()
       
    68     {
       
    69     Release();
       
    70     }
       
    71 
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CThumbnailImageDecoder::CreateL()
       
    75 // Creates thumbnail of image
       
    76 // -----------------------------------------------------------------------------
       
    77 //
       
    78 void CThumbnailImageDecoder::CreateL( RFile64& aFile, MThumbnailProviderObserver&
       
    79     aObserver, const CThumbnailManager::TThumbnailQualityPreference aQualityPreference, const
       
    80     TDataType& aMimeType, const TSize& aSize)
       
    81     {
       
    82     TN_DEBUG1( "CThumbnailImageDecoder::CreateL() start" );
       
    83 
       
    84     iBuffer = NULL;
       
    85     iSize = aSize;
       
    86     iMimeType = aMimeType;
       
    87     iObserver = &aObserver;
       
    88     iFile = aFile;
       
    89 
       
    90     CreateDecoderL( aQualityPreference );
       
    91 
       
    92     const TFrameInfo info( iDecoder->FrameInfo());
       
    93     if (( info.iOverallSizeInPixels.iWidth < 1 ) || (
       
    94         info.iOverallSizeInPixels.iHeight < 1 ))
       
    95         {
       
    96         User::Leave( KErrCorrupt );
       
    97         }
       
    98     iFrameInfoFlags = info.iFlags;
       
    99     iOriginalSize = info.iOverallSizeInPixels;
       
   100     
       
   101     TN_DEBUG1( "CThumbnailImageDecoder::CreateL() end" );
       
   102     }
       
   103 
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CThumbnailImageDecoder::CreateL()
       
   107 // Creates thumbnail of image
       
   108 // -----------------------------------------------------------------------------
       
   109 //
       
   110 void CThumbnailImageDecoder::CreateL( const TDesC8* aBuffer, MThumbnailProviderObserver&
       
   111     aObserver, const CThumbnailManager::TThumbnailQualityPreference aQualityPreference, const
       
   112     TDataType& aMimeType, const TSize& aSize)
       
   113     {
       
   114     TN_DEBUG1( "CThumbnailImageDecoder::CreateL() start" );
       
   115 
       
   116     iSize = aSize;
       
   117     iMimeType = aMimeType;
       
   118     iObserver = &aObserver;
       
   119     iBuffer = aBuffer;
       
   120     
       
   121     CreateDecoderL( aQualityPreference );
       
   122 
       
   123     const TFrameInfo info( iDecoder->FrameInfo());
       
   124     if (( info.iOverallSizeInPixels.iWidth < 1 ) || (
       
   125         info.iOverallSizeInPixels.iHeight < 1 ))
       
   126         {
       
   127         User::Leave( KErrCorrupt );
       
   128         }
       
   129     iFrameInfoFlags = info.iFlags;
       
   130     iOriginalSize = info.iOverallSizeInPixels;
       
   131     
       
   132     TN_DEBUG1( "CThumbnailImageDecoder::CreateL() end" );
       
   133     }
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // CThumbnailImageDecoder::DecodeL()
       
   137 // Decode the thumbnail image
       
   138 // -----------------------------------------------------------------------------
       
   139 //
       
   140 void CThumbnailImageDecoder::DecodeL( const TDisplayMode aDisplayMode, const CThumbnailManager::TThumbnailFlags aFlags)
       
   141     {
       
   142     TN_DEBUG1( "CThumbnailImageDecoder::DecodeL() start" );
       
   143     
       
   144     // Create the bitmap
       
   145     if ( !iBitmap )
       
   146         {
       
   147         iBitmap = new( ELeave )CFbsBitmap();
       
   148         }
       
   149     
       
   150     TN_DEBUG3( "CThumbnailImageDecoder::DecodeL() %d x %d", iSize.iWidth, iSize.iHeight );
       
   151     if( iOriginalSize.iWidth < iOriginalSize.iHeight )
       
   152         {
       
   153         TInt height = iSize.iHeight;
       
   154         iSize.iHeight = iSize.iWidth;
       
   155         iSize.iWidth = height;
       
   156         iPortrait = ETrue;
       
   157         TN_DEBUG3( "CThumbnailImageDecoder::DecodeL() %d x %d", iSize.iWidth, iSize.iHeight );
       
   158         }
       
   159     else
       
   160         {
       
   161         iPortrait = EFalse;
       
   162         }
       
   163     
       
   164     TN_DEBUG3( "CThumbnailImageDecoder::DecodeL() iOriginalSize = %d x %d", iOriginalSize.iWidth, iOriginalSize.iHeight );
       
   165 
       
   166     //Size in both x and y dimension must be non-zero, positive value
       
   167     TSize loadSize( iOriginalSize) ;
       
   168     
       
   169     
       
   170     if(iOriginalSize.iHeight < iSize.iHeight || iOriginalSize.iWidth < iSize.iWidth )
       
   171         {
       
   172         loadSize = iOriginalSize;
       
   173         TN_DEBUG1( "CThumbnailImageDecoder::DecodeL() LoadSize is OriginalSize" );
       
   174         }
       
   175     else if((iFrameInfoFlags& TFrameInfo::EFullyScaleable || IsSvg()) && aFlags == !CThumbnailManager::ECropToAspectRatio)
       
   176         {
       
   177         loadSize = iSize;
       
   178         TN_DEBUG1( "CThumbnailImageDecoder::DecodeL() EFullyScaleable start" );
       
   179         const TReal32 srcAspect = static_cast < TReal32 > (
       
   180               iOriginalSize.iWidth ) / iOriginalSize.iHeight;
       
   181 
       
   182           // set loadsize to maximum size within target size 
       
   183           if ( (loadSize.iHeight * srcAspect) <= loadSize.iWidth )
       
   184               {
       
   185               TReal trg = 0;
       
   186               TReal src( loadSize.iHeight * srcAspect );
       
   187               Math::Round( trg, src, 0 );
       
   188               loadSize.SetSize( trg, loadSize.iHeight );
       
   189               }
       
   190           else
       
   191               {
       
   192               TReal trg;
       
   193               TReal src( loadSize.iWidth / srcAspect );
       
   194               Math::Round( trg, src, 0 );
       
   195               loadSize.SetSize( loadSize.iWidth, trg );
       
   196               }
       
   197         
       
   198         TN_DEBUG3( "CThumbnailImageDecoder::DecodeL() EFullyScaleable loadSize = %d x %d", loadSize.iWidth, loadSize.iHeight );
       
   199         }
       
   200     else 
       
   201         {
       
   202         
       
   203         // Size reduction factor. 1/1, 1/2, 1/4, and 1/8 are possible values for all
       
   204         // plug-ins. SVG graphics can be rendered at any size.
       
   205         TInt reductionFactor = 1;
       
   206         while ( reductionFactor < KMaximumReductionFactor && ( iSize.iWidth <
       
   207             loadSize.iWidth / 2 ) && ( iSize.iHeight < loadSize.iHeight / 2 ))
       
   208             {
       
   209             // magic: use loadSize that is half of previous size
       
   210             loadSize.iWidth /= 2;
       
   211             loadSize.iHeight /= 2;
       
   212             reductionFactor *= 2;
       
   213             }
       
   214         // If original size is not an exact multiple of reduction factor,
       
   215         // we need to round loadSize up
       
   216         if ( reductionFactor && iOriginalSize.iWidth % reductionFactor )
       
   217             {
       
   218             loadSize.iWidth++;
       
   219             }
       
   220         if ( reductionFactor && iOriginalSize.iHeight % reductionFactor )
       
   221             {
       
   222             loadSize.iHeight++;
       
   223             }
       
   224         TN_DEBUG4( 
       
   225             "CThumbnailImageDecoder::DecodeL() - loadSize = (%d,%d) reduction = 1/%d ", loadSize.iWidth, loadSize.iHeight, reductionFactor );
       
   226         }
       
   227 
       
   228     User::LeaveIfError( iBitmap->Create( loadSize, aDisplayMode ));
       
   229 
       
   230     iDecoder->Convert( &iStatus, * iBitmap );
       
   231     while ( iStatus == KErrUnderflow )
       
   232         {
       
   233         iDecoder->ContinueConvert( &iStatus );
       
   234         }
       
   235     
       
   236     SetActive();
       
   237     
       
   238     TN_DEBUG1( "CThumbnailImageDecoder::DecodeL() end" );
       
   239     }
       
   240 
       
   241 
       
   242 // -----------------------------------------------------------------------------
       
   243 // CThumbnailImageDecoder::Release()
       
   244 // Releases resources
       
   245 // -----------------------------------------------------------------------------
       
   246 //
       
   247 void CThumbnailImageDecoder::Release()
       
   248     {
       
   249     Cancel();
       
   250     delete iJpegReadBuffer;
       
   251     iJpegReadBuffer = NULL;
       
   252     delete iExifThumbImage;
       
   253     iExifThumbImage = NULL;
       
   254     delete iDecoder;
       
   255     iDecoder = NULL;
       
   256     }
       
   257 
       
   258 
       
   259 // -----------------------------------------------------------------------------
       
   260 // CThumbnailImageDecoder::DoCancel()
       
   261 // -----------------------------------------------------------------------------
       
   262 //
       
   263 void CThumbnailImageDecoder::DoCancel()
       
   264     {
       
   265     if ( iDecoder )
       
   266         {
       
   267         iDecoder->Cancel();
       
   268         delete iJpegReadBuffer;
       
   269         iJpegReadBuffer = NULL;
       
   270         delete iExifThumbImage;
       
   271         iExifThumbImage = NULL;
       
   272         delete iDecoder;
       
   273         iDecoder = NULL;
       
   274         }
       
   275     }
       
   276 
       
   277 
       
   278 // -----------------------------------------------------------------------------
       
   279 // CThumbnailImageDecoder::RunL()
       
   280 // -----------------------------------------------------------------------------
       
   281 //
       
   282 void CThumbnailImageDecoder::RunL()
       
   283     {
       
   284     // This call takes ownership of iBitmap
       
   285     iObserver->ThumbnailProviderReady( iStatus.Int(), iBitmap, iOriginalSize, iEXIF, iPortrait );
       
   286 
       
   287     iBitmap = NULL; // owned by server now
       
   288     Release();
       
   289     }
       
   290 
       
   291 
       
   292 // -----------------------------------------------------------------------------
       
   293 // CThumbnailImageDecoder::IsJpeg()
       
   294 // -----------------------------------------------------------------------------
       
   295 //
       
   296 TBool CThumbnailImageDecoder::IsJpeg()
       
   297     {
       
   298     __ASSERT_DEBUG(( iMimeType.Des() != KNullDesC ), ThumbnailPanic(
       
   299         EThumbnailEmptyDescriptor ));
       
   300 
       
   301     if ( KJpegMime() == iMimeType.Des())
       
   302         {
       
   303         return ETrue;
       
   304         }
       
   305     return EFalse;
       
   306     }
       
   307 
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // CThumbnailImageDecoder::IsSvg()
       
   311 // -----------------------------------------------------------------------------
       
   312 //
       
   313 TBool CThumbnailImageDecoder::IsSvg()
       
   314     {
       
   315     __ASSERT_DEBUG(( iMimeType.Des() != KNullDesC ), ThumbnailPanic(
       
   316         EThumbnailEmptyDescriptor ));
       
   317 
       
   318     if ( KSvgMime() == iMimeType.Des())
       
   319         {
       
   320         return ETrue;
       
   321         }
       
   322     return EFalse;
       
   323     }
       
   324 
       
   325 
       
   326 // -----------------------------------------------------------------------------
       
   327 // CThumbnailImageDecoder::CreateDecoderL
       
   328 // Creates image decoder
       
   329 // -----------------------------------------------------------------------------
       
   330 //
       
   331 void CThumbnailImageDecoder::CreateDecoderL( CThumbnailManager::TThumbnailQualityPreference
       
   332     aFlags )
       
   333     {
       
   334     TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() start" );
       
   335     
       
   336     TBool thumbFound( EFalse );
       
   337     
       
   338     // If the image is in jpeg format, try to get thumbnail from EXIF data (if EOptimizeForQuality not set)
       
   339     if ( IsJpeg() && !( aFlags == CThumbnailManager::EOptimizeForQuality ))
       
   340         {
       
   341         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() crete exif decoder" );
       
   342         TRAPD( err, CreateExifDecoderL( aFlags ));
       
   343         thumbFound = ( err == KErrNone );
       
   344         iEXIF = ETrue;
       
   345         }
       
   346 
       
   347     if ( !thumbFound )
       
   348         {
       
   349         iEXIF = EFalse;
       
   350         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() crete normal decoder" );
       
   351         
       
   352         delete iDecoder;
       
   353         iDecoder = NULL;
       
   354         
       
   355         TFileName fullName;
       
   356         if ( !iBuffer )
       
   357             {
       
   358             iFile.FullName( fullName );
       
   359             }
       
   360         
       
   361         CImageDecoder::TOptions options;
       
   362         if ( aFlags == CThumbnailManager::EOptimizeForQuality )
       
   363             {
       
   364             options = ( CImageDecoder::TOptions )( CImageDecoder
       
   365                 ::EOptionNoDither );
       
   366             }
       
   367         else
       
   368             {
       
   369             options = ( CImageDecoder::TOptions )( CImageDecoder
       
   370                 ::EOptionNoDither | CImageDecoder::EPreferFastDecode );
       
   371             }
       
   372 
       
   373         if ( IsSvg())
       
   374             {
       
   375             if ( !iBuffer )
       
   376                 {
       
   377                 iDecoder = CImageDecoder::FileNewL( iFile, ContentAccess::EPeek, 
       
   378                         options, KImageTypeSVGUid, KNullUid, KNullUid );
       
   379                 
       
   380                 TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - CImageDecoder created" );
       
   381                 }
       
   382             else
       
   383                 {
       
   384                 TRAPD( decErr, iDecoder = CImageDecoder::DataNewL( iFs, *iBuffer, options, KImageTypeSVGUid ) );
       
   385                 
       
   386                 if ( decErr != KErrNone )
       
   387                     {
       
   388                     TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - error 1" );
       
   389                     
       
   390                     User::Leave( decErr );
       
   391                     }
       
   392                 
       
   393                 TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - CImageDecoder created" );
       
   394                 }
       
   395             }
       
   396         else if ( !IsJpeg())
       
   397             {
       
   398             if ( !iBuffer )
       
   399                 {
       
   400                 iDecoder = CImageDecoder::FileNewL( iFile, ContentAccess::EPeek, options );
       
   401                 
       
   402                 TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - CImageDecoder created" );
       
   403                 }
       
   404             else
       
   405                 {
       
   406                 TRAPD( decErr, iDecoder = CImageDecoder::DataNewL( iFs, *iBuffer, iMimeType.Des8(), options) );
       
   407                 
       
   408                 if ( decErr != KErrNone )
       
   409                     {                        
       
   410                     // don't force any mime type
       
   411                     TRAPD( decErr, iDecoder = CImageDecoder::DataNewL( iFs, *iBuffer, options ) );
       
   412                     if ( decErr != KErrNone )
       
   413                         {                        
       
   414                         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - error 2" );
       
   415                         
       
   416                         User::Leave( decErr );
       
   417                         }
       
   418                     }
       
   419                 
       
   420                 TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - CImageDecoder created" );
       
   421                 }
       
   422             }
       
   423         else
       
   424             {
       
   425             
       
   426             if ( !iBuffer )
       
   427                 {
       
   428                 TRAPD( decErr, iDecoder = CExtJpegDecoder::FileNewL(
       
   429                         CExtJpegDecoder::EHwImplementation, iFs, fullName, options) );
       
   430                 
       
   431                 if ( decErr != KErrNone )
       
   432                     {
       
   433                     TRAP( decErr, iDecoder = CExtJpegDecoder::FileNewL(
       
   434                             CExtJpegDecoder::ESwImplementation, iFs, fullName, options) );
       
   435                     
       
   436                     if ( decErr != KErrNone )
       
   437                         {
       
   438                         iDecoder = CImageDecoder::FileNewL( iFile, ContentAccess::EPeek, options );
       
   439                         
       
   440                         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - CImageDecoder created" );
       
   441                         }
       
   442                     else
       
   443                         {
       
   444                         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - SW CExtJpegDecoder created" );
       
   445                         }
       
   446                     }
       
   447                 else 
       
   448                     {
       
   449                     TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - HW CExtJpegDecoder created" );
       
   450                     }
       
   451                 }
       
   452             else
       
   453                 {
       
   454                 TRAPD( decErr, iDecoder = CExtJpegDecoder::DataNewL(
       
   455                         CExtJpegDecoder::EHwImplementation, iFs, *iBuffer, options ));
       
   456                 
       
   457                 if ( decErr != KErrNone )
       
   458                     {
       
   459                     TRAP( decErr, iDecoder = CExtJpegDecoder::DataNewL(
       
   460                             CExtJpegDecoder::ESwImplementation, iFs, *iBuffer, options ));
       
   461                     
       
   462                     if ( decErr != KErrNone )
       
   463                         {                        
       
   464                         TRAPD( decErr, iDecoder = CImageDecoder::DataNewL( iFs, *iBuffer, iMimeType.Des8(), options) );
       
   465                         
       
   466                         if ( decErr != KErrNone )
       
   467                             {                        
       
   468                             // don't force any mime type
       
   469                             TRAPD( decErr, iDecoder = CImageDecoder::DataNewL( iFs, *iBuffer, options ) );
       
   470                             if ( decErr != KErrNone )
       
   471                                 {                                
       
   472                                 TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - error 3" );
       
   473                                 
       
   474                                 User::Leave( decErr );
       
   475                                 }
       
   476                             }
       
   477                         
       
   478                         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - CImageDecoder created" );
       
   479                         }
       
   480                     else
       
   481                         {
       
   482                         TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - SW CExtJpegDecoder created" );
       
   483                         }               
       
   484                     }
       
   485                 else
       
   486                     {
       
   487                     TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() - HW CExtJpegDecoder created" );
       
   488                     }               
       
   489                 }
       
   490             }
       
   491         }
       
   492     
       
   493     TN_DEBUG1( "CThumbnailImageDecoder::CreateDecoderL() end" );
       
   494     }
       
   495 
       
   496 
       
   497 // -----------------------------------------------------------------------------
       
   498 // CThumbnailImageDecoder::CreateExifDecoderL()
       
   499 // -----------------------------------------------------------------------------
       
   500 //
       
   501 void CThumbnailImageDecoder::CreateExifDecoderL( CThumbnailManager
       
   502     ::TThumbnailQualityPreference aFlags )
       
   503     {
       
   504     TN_DEBUG1( "CThumbnailImageDecoder::CreateExifDecoderL() start" );
       
   505     
       
   506     // If the image is in jpeg format, try to get thumbnail from EXIF data.
       
   507     CExifRead* reader = NULL;
       
   508     
       
   509     if ( !iBuffer )
       
   510         {    
       
   511         TInt64 size( 0 );
       
   512         User::LeaveIfError( iFile.Size( size ));
       
   513     
       
   514         TInt readSize = Min( size, KJpegLoadBufferSize );
       
   515     
       
   516         delete iJpegReadBuffer;
       
   517         iJpegReadBuffer = NULL;
       
   518         iJpegReadBuffer = HBufC8::NewL( readSize );
       
   519         TPtr8 localBuffer = iJpegReadBuffer->Des();
       
   520     
       
   521         User::LeaveIfError( iFile.Read( localBuffer, readSize ));
       
   522         reader = CExifRead::NewL( localBuffer, CExifRead::ENoJpeg );
       
   523         }
       
   524     else
       
   525         {
       
   526         reader = CExifRead::NewL( *iBuffer, CExifRead::ENoJpeg );
       
   527         }
       
   528     
       
   529     
       
   530     CleanupStack::PushL( reader );
       
   531 
       
   532     iExifThumbImage = reader->GetThumbnailL();
       
   533     CleanupStack::PopAndDestroy( reader );
       
   534 
       
   535     User::LeaveIfNull( iExifThumbImage );
       
   536 
       
   537     delete iDecoder;
       
   538     iDecoder = NULL;
       
   539 
       
   540     CImageDecoder::TOptions options;
       
   541     if ( aFlags == CThumbnailManager::EOptimizeForQuality )
       
   542         {
       
   543         options = ( CImageDecoder::TOptions )( CImageDecoder::EOptionNoDither );
       
   544         }
       
   545     else
       
   546         {
       
   547         options = ( CImageDecoder::TOptions )( CImageDecoder::EOptionNoDither |
       
   548             CImageDecoder::EPreferFastDecode );
       
   549         }
       
   550 
       
   551     TRAPD( err, iDecoder = CExtJpegDecoder::DataNewL( iFs, * iExifThumbImage,
       
   552         options ));
       
   553 
       
   554     if ( err == KErrNotFound || err == KErrNotSupported )
       
   555         {
       
   556         delete iDecoder;
       
   557         iDecoder = NULL;
       
   558 
       
   559         iDecoder = CImageDecoder::DataNewL( iFs, * iExifThumbImage, options );
       
   560         }
       
   561     else
       
   562         {
       
   563         TN_DEBUG2( "CThumbnailImageDecoder::CreateExifDecoderL() - CExtJpegDecoder err == %d", err );
       
   564         User::LeaveIfError( err );
       
   565         }
       
   566 
       
   567 /*
       
   568     // If the Exif thumbnail is smaller than requested it will not be used
       
   569     TFrameInfo frame = iDecoder->FrameInfo( 0 );
       
   570     
       
   571     if ( frame.iOverallSizeInPixels.iWidth < iSize.iWidth ||
       
   572         frame.iOverallSizeInPixels.iHeight < iSize.iHeight ) 
       
   573         {
       
   574         User::Leave( KErrGeneral );
       
   575         }
       
   576     */
       
   577     TN_DEBUG1( "CThumbnailImageDecoder::CreateExifDecoderL() end" );
       
   578     }
       
   579 
       
   580 
       
   581 // -----------------------------------------------------------------------------
       
   582 // CThumbnailImageDecoder::CreateExifDecoderL()
       
   583 // Returns size of original image
       
   584 // -----------------------------------------------------------------------------
       
   585 //
       
   586 const TSize& CThumbnailImageDecoder::OriginalSize()const
       
   587     {
       
   588     return iOriginalSize;
       
   589     }
       
   590 
       
   591 //End of file