--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditorengine/EngineWrapper/src/ImageEditorEngineWrapper.cpp Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,1968 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "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:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+
+// INCLUDES
+#include <bautils.h>
+#include <eikenv.h>
+#include <aknutils.h>
+#include <e32math.h>
+
+//#include "ImageEditorPluginBase.hrh"
+#include "platform_security_literals.hrh"
+
+#include "ImageEditorEngineWrapper.h"
+#include "CFilterStack.h"
+#include "MImageFilter.h"
+#include "SystemParameters.h"
+#include "ImageEditorError.h"
+#include "ImageEditorUtils.h"
+#include "EditorVersion.h"
+
+
+#include "CExifParser.h"
+#include "TBitmapHandle.h"
+#include "MJpegSave.h"
+#include "JpegSaveFactory.h"
+
+
+// Debug logger definitions
+#include "imageeditordebugutils.h"
+_LIT( KEngineWrapperLogFile,"EngineWrapper.log" );
+
+
+// CONSTANTS
+
+// Minimum source image x-y value that the engine is able to render
+const TInt KObMinSourceDimension = 16;
+
+// EXIF thumbnail quality
+const TInt KThumbnailJpegQuality = 60; // [0,100]
+const TInt KThumbnailMaxDimension = 160;
+
+// Used fixed point resolution for scales
+const TInt KScaleBits = 12;
+
+const TReal KZoomScaleFactor = 0.5;
+
+// Comment tag to be written to the EXIF data of JPEG file.
+_LIT8( KImageEditorExifComment, "Edited with Nokia Image Editor %d.%d.%d" );
+
+
+// Filter paths
+_LIT(KFilterJpegSource, "FilterJpegSource.dll");
+_LIT(KFilterIclSource, "FilterIclSource.dll");
+_LIT(KFilterTarget, "FilterJpegTarget.dll");
+_LIT(KFilterBuffer, "FilterBuffer.dll");
+_LIT(KFilterScale, "FilterScale.dll");
+_LIT(KFilterRotate, "FilterRotate.dll");
+
+//=============================================================================
+EXPORT_C CEngineWrapper * CEngineWrapper::NewL ()
+{
+ LOG_INIT ( KEngineWrapperLogFile );
+
+ CEngineWrapper * self = new (ELeave) CEngineWrapper;
+ CleanupStack::PushL (self);
+ self->ConstructL();
+ CleanupStack::Pop(); // self
+ return self;
+}
+
+//=============================================================================
+EXPORT_C CEngineWrapper::~CEngineWrapper ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::~CEngineWrapper");
+ Cleanup();
+
+ delete iExifParser;
+ iExifParser = NULL;
+
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::CreateJpegSourceL (const TDesC & aFileName)
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL" );
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL\taFileName: %S", &aFileName );
+#endif // VERBOSE
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Add JPEG source to engine
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL --- Add jpeg source" );
+ if ( iMainEngine->NumFilters() == 0 )
+ {
+ iMainEngine->AddFilterL ( KFilterJpegSource );
+ }
+ else if ( IsSameString ( (TUint8*)iMainEngine->Filter(0)->Type(), (TUint8*)"iclsource" ) )
+ {
+ iMainEngine->RemoveFilter (0);
+ iMainEngine->AddFilterL (KFilterJpegSource, 0);
+ }
+ else if ( !IsSameString ( (TUint8*)iMainEngine->Filter(0)->Type(), (TUint8*)"jpegsource" ) )
+ {
+ iMainEngine->AddFilterL (KFilterJpegSource, 0);
+ }
+ iCmd.Copy ( _L("file \""));
+ iCmd.Append ( aFileName );
+ iCmd.Append ( _L("\""));
+ LOGFMT ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL: Cmd: %S", &aFileName );
+ iMainEngine->FunctionL ( 0, iCmd );
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL --- Jpeg source added" );
+ iMainEngine->FunctionL ( 0, _L("loadimage"));
+
+ // Get source image size
+ TRect rect = iMainEngine->Filter (0)->Rect();
+ iSourceSize = iMainEngine->Filter (0)->ViewPortSize();
+ LOGFMT ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL: source width: %d", iSourceSize.iWidth);
+ LOGFMT ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL: source height: %d", iSourceSize.iHeight);
+
+ // Check that the source image is of minimum size
+ if (iSourceSize.iWidth < KObMinSourceDimension || iSourceSize.iHeight < KObMinSourceDimension)
+ {
+ User::Leave (KSIEEOpenFile);
+ }
+
+ // Initialize crop parameters
+ iBoundingRect.iTl.iX = 0;
+ iBoundingRect.iTl.iY = 0;
+ iBoundingRect.iBr.iX = iSourceSize.iWidth;
+ iBoundingRect.iBr.iY = iSourceSize.iHeight;
+ iScale = 1.0;
+ iMaxScale = 1.0;
+ iMinScale = (TReal)iScreenSize.iWidth / iSourceSize.iWidth;
+ iPanX = iSourceSize.iWidth * 0.5;
+ iPanY = iSourceSize.iHeight * 0.5;
+ iPanStep = 128.0;
+ iZoomMode = EZoomNormal;
+
+ // Initialize system parameters
+ iSysPars->SourceSize() = iSourceSize;
+ iSysPars->Scale() = 1.0;
+
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL --- Read EXIF data" );
+
+ // Read EXIF data pointer
+ iCmd.Copy ( _L("exifdata"));
+ TUint8 * exifptr = (TUint8 *)iMainEngine->FunctionL ( 0, iCmd );
+
+ // Read EXIF data length
+ iCmd.Copy ( _L("exiflength"));
+ TInt exiflen = (TInt)iMainEngine->FunctionL ( 0, iCmd );
+
+ // Create and initialize EXIF parser
+ TPtrC8 exifdata (exifptr, exiflen);
+ if (iExifParser)
+ {
+ delete iExifParser;
+ iExifParser = NULL;
+ }
+
+ iExifParser = CExifParser::NewL ();
+ TRAPD( err, iExifParser->ParseL (exifdata) );
+ if (KErrNone == err)
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL --- EXIF data read." );
+ }
+ else
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL --- FAILED to parse EXIF data. Ignored." );
+ }
+
+
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::CreateJpegTargetL (
+ const TDesC & aFileName,
+ const TInt aQuality,
+ const TSize * aSize
+ )
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL" );
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL\taFileName: %S", &aFileName );
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL\taQuality: %d", aQuality );
+ if (aSize)
+ {
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL\taSize->iWidth: %d", aSize->iWidth);
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL\taSize->iHeight: %d", aSize->iHeight);
+ }
+ else
+ {
+ LOG( KEngineWrapperLogFile, "aSize == NULL" );
+ }
+
+#endif // VERBOSE
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+ if ( aQuality < 0 || aQuality > 100)
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL: Invalid parameter aQuality!" );
+ User::Panic (KEnginePanic, KEnginePanicParameter);
+ }
+ if ( aSize && ( (aSize->iWidth < 0 || aSize->iHeight < 0) ) )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL: Invalid parameter aSize!" );
+ User::Panic (KEnginePanic, KEnginePanicParameter);
+ }
+
+ // Remove source buffer
+ iMainEngine->FunctionL (0, _L("fileoutput"));
+
+ // Remove screen buffer
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL --- Remove screen buffer" );
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(iMainEngine->NumFilters() - 1)->Type(), (TUint8*)"buffer" ) )
+ {
+ iMainEngine->RemoveFilter(iMainEngine->NumFilters() - 1);
+ }
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL --- Screen buffer removed" );
+
+ // Remove jpeg target buffer
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(iMainEngine->NumFilters() - 1)->Type(), (TUint8*)"jpegtarget" ) )
+ {
+ iMainEngine->RemoveFilter(iMainEngine->NumFilters() - 1);
+ }
+
+ // Remove scale buffer, if image is not scaled
+ if ( iSysPars->Scale() == 1.0 )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL --- Remove screen scale filter." );
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(iMainEngine->NumFilters() - 1)->Type(), (TUint8*)"scale" ) )
+ {
+ iMainEngine->RemoveFilter(iMainEngine->NumFilters() - 1);
+ }
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL --- Screen scale filter removed." );
+ }
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL --- Add jpeg target filter." );
+ iMainEngine->AddFilterL ( KFilterTarget );
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegTargetL --- Jpeg target filter added." );
+
+ // If external target size is given, set it to target.
+ if ( aSize )
+ {
+ iCmd.Format( _L("width %d height %d"), aSize->iWidth, aSize->iHeight );
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 1, iCmd );
+ }
+
+ // Set the scaled source size to target
+ if ( iSysPars->Scale() != 1.0 )
+ {
+ TReal scale = iSysPars->Scale();
+ TSize tgtsize = iMainEngine->Filter ( iMainEngine->NumFilters() - 3 )->ViewPortSize();
+ tgtsize.iWidth = (TInt)(tgtsize.iWidth * scale + 0.5);
+ tgtsize.iHeight = (TInt)(tgtsize.iHeight * scale + 0.5);
+ iCmd.Format( _L("width %d height %d"), tgtsize.iWidth, tgtsize.iHeight);
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 1, iCmd );
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 2, _L("nop"));
+ }
+
+ // Store save file name
+ iTargetFile.Copy ( aFileName );
+
+ LOG ( KEngineWrapperLogFile, "CreateJpegTargetL: Sink created" );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::CreateIclSourceL (const TDesC & aFileName)
+{
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL" );
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL\taFileName: %S", &aFileName );
+#endif // VERBOSE
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Add JPEG source to engine
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL --- Add icl source" );
+ if ( iMainEngine->NumFilters() == 0 )
+ {
+ iMainEngine->AddFilterL ( KFilterIclSource );
+ }
+ else if ( IsSameString ( (TUint8*)iMainEngine->Filter(0)->Type(), (TUint8*)"jpegsource" ) )
+ {
+ iMainEngine->RemoveFilter(0);
+ iMainEngine->AddFilterL ( KFilterIclSource, 0);
+ }
+ else if ( !IsSameString ( (TUint8*)iMainEngine->Filter(0)->Type(), (TUint8*)"iclsource" ) )
+ {
+ iMainEngine->AddFilterL ( KFilterIclSource, 0);
+ }
+ iCmd.Copy (_L("file \""));
+ iCmd.Append ( aFileName );
+ iCmd.Append (_L("\""));
+ LOGFMT ( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL: Cmd: %S", &iCmd );
+ iMainEngine->FunctionL ( 0, iCmd );
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL --- Icl source added" );
+ iMainEngine->FunctionL ( 0, _L("loadimage"));
+
+ // Get source image size
+ TRect rect = iMainEngine->Filter (0)->Rect();
+ iSourceSize = iMainEngine->Filter (0)->ViewPortSize();
+ LOGFMT ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL: source width: %d", iSourceSize.iWidth);
+ LOGFMT ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL: source height: %d", iSourceSize.iHeight);
+
+ // Check that the source image is of minimum size
+ if (iSourceSize.iWidth < KObMinSourceDimension || iSourceSize.iHeight < KObMinSourceDimension)
+ {
+ User::Leave (KSIEEOpenFile);
+ }
+
+ // Initialize crop parameters
+ iScale = 1.0;
+ iMaxScale = 1.0;
+ iMinScale = (TReal)iScreenSize.iWidth / iSourceSize.iWidth;
+ iPanX = iSourceSize.iWidth * 0.5;
+ iPanY = iSourceSize.iHeight * 0.5;
+ iPanStep = 128.0;
+ iZoomMode = EZoomNormal;
+
+ // Initialize system parameters
+ iSysPars->SourceSize() = iSourceSize;
+ iSysPars->Scale() = 1.0;
+
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateIclSourceL --- Create EXIF parser" );
+
+ if (iExifParser)
+ {
+ delete iExifParser;
+ iExifParser = NULL;
+ }
+
+ iExifParser = CExifParser::NewL ();
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateJpegSourceL --- EXIF parser created." );
+
+
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::CreateRGB888TargetL ()
+{
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL " );
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "\tiScreenSize.w: %d", iScreenSize.iWidth);
+ LOGFMT( KEngineWrapperLogFile, "\tiScreenSize.h: %d", iScreenSize.iHeight);
+#endif
+
+ // Create source buffer
+ iMainEngine->FunctionL (0, _L("bufferoutput"));
+
+ // Remove target filter and add screen buffer
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL --- Add buffer target." );
+ TInt n = iMainEngine->NumFilters();
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(n - 1)->Type(), (TUint8*)"jpegtarget") )
+ {
+ iMainEngine->RemoveFilter(n - 1);
+ iMainEngine->AddFilterL ( KFilterBuffer );
+ }
+ else if ( !IsSameString ( (TUint8*)iMainEngine->Filter(n - 1)->Type(), (TUint8*)"buffer" ) )
+ {
+ iMainEngine->AddFilterL ( KFilterBuffer );
+ }
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL --- Buffer target added." );
+
+ // Set buffer size
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL --- Set buffer size ");
+ iCmd.Format( _L("width %d height %d"), iScreenSize.iWidth, iScreenSize.iHeight );
+ LOGDES (KEngineWrapperLogFile, iCmd);
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 1, iCmd );
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL --- Buffer size set." );
+
+ // Set scale buffer before screen buffer
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL --- Add screen buffer scale filter");
+ if ( !IsSameString ( (TUint8*)iMainEngine->Filter(iMainEngine->NumFilters() - 2)->Type(), (TUint8*)"scale") )
+ {
+ iMainEngine->AddFilterL ( KFilterScale, iMainEngine->NumFilters() - 1);
+ }
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 2, iCmd );
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL --- Screen buffer scale filter added.");
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::CreateRGB888TargetL: Sink created" );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::SetScreenSizeL (const TSize & aSize)
+{
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::SetScreenSizeL" );
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::SetScreenSizeL\taSize.iWidth: %d", aSize.iWidth );
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::SetScreenSizeL\taSize.iHeight: %d", aSize.iHeight );
+#endif // VERBOSE
+
+ // SANITY CHECKS
+ if ( aSize.iWidth < 0 || aSize.iHeight < 0)
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::SetScreenSizeL: Invalid parameter aSize!" );
+ User::Panic (KEnginePanic, KEnginePanicParameter);
+ }
+
+ if ( aSize != iScreenSize )
+ {
+ iScreenSize = aSize;
+
+ // Set buffer size
+ TInt n = iMainEngine->NumFilters();
+ if (n > 2)
+ {
+ if ( IsSameString ((TUint8*)iMainEngine->Filter(n - 1)->Type(), (TUint8*) "buffer" ) )
+ {
+ iCmd.Format( _L("width %d height %d"), iScreenSize.iWidth, iScreenSize.iHeight);
+ iMainEngine->FunctionL ( n - 1, iCmd );
+ iMainEngine->FunctionL ( n - 2, _L("nop"));
+ UpdateCropRectL();
+ }
+ }
+ }
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::AddFilterL (const TDesC & aFilterName)
+{
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::AddFilterL (TDes & aFilterName: %S)", &aFilterName );
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::AddFilterL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Check whether the filter is found
+ TFileName filtername;
+ filtername.Copy (aFilterName);
+
+ /*
+ // no need for this as AddFilterL will leave if there is an error
+ if (FileExists (filtername) )
+ {
+ TParse parse;
+ User::LeaveIfError( parse.Set( aFilterName ,NULL, NULL ) );
+ filtername = parse.NameAndExt();
+ };
+ */
+
+ TInt n = iMainEngine->NumFilters();
+ if (n >= 2)
+ {
+ iMainEngine->AddFilterL ( filtername, n - 2 );
+ }
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::AddFilterL: Filter added" );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::SetParamsL (const TDesC & aParam)
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::SetParamsL " );
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::SetParamsL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Initialize error value
+ TInt n = iMainEngine->NumFilters();
+ if ( n > 2 )
+ {
+ LOGDES( KEngineWrapperLogFile, aParam );
+ iMainEngine->FunctionL ( n - 3, aParam );
+ }
+
+
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(n - 3)->Type(), (TUint8*) "rotate" ) )
+ {
+ if (iScale == 1.0)
+ {
+ ComputeBoundingRectL();
+ }
+ UpdateCropRectL();
+ }
+
+
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::SetParamsL: Parameters set " );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::RenderL (TInt* /*aMultiSessionBlockCount*/)
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::RenderL" );
+
+ // SANITY CHECKS
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::RenderL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ TInt n = iMainEngine->NumFilters();
+ for ( TInt i = 0; i < iMainEngine->NumFilters(); ++i)
+ {
+ iMainEngine->FunctionL (i, _L("nop"));
+ TBuf<100> buf;
+ buf.Copy(TPtrC8 ( (TUint8 *)iMainEngine->Filter(i)->Type() ));
+ LOGDES (KEngineWrapperLogFile, buf) ;
+ TRect rect = iMainEngine->Filter(i)->Rect();
+ buf.Format( _L("%d %d %d %d"), rect.iTl.iX, rect.iTl.iY, rect.iBr.iX, rect.iBr.iY);
+ LOGDES (KEngineWrapperLogFile, buf) ;
+ }
+
+ // Render to buffer target
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(n - 1)->Type(), (TUint8*) "buffer" ) )
+ {
+ iCmd.Copy (_L("getbitmap"));
+ if ( iRenderScaleBuffer )
+ {
+ iMainEngine->FunctionL ( 0, _L("loadimage"));
+ iRenderScaleBuffer = EFalse;
+ for ( TInt i = 0; i < iMainEngine->NumFilters(); ++i)
+ {
+ iMainEngine->FunctionL (i, _L("nop"));
+ }
+ }
+
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::RenderL -- Render screen buffer." );
+ TUint32 * buffer = (TUint32 *)iMainEngine->FunctionL ( n - 1, iCmd );
+ CopyBufferL (buffer);
+ }
+
+ // Render to JPEG target
+ else if ( IsSameString ( (TUint8*)iMainEngine->Filter(n - 1)->Type(), (TUint8*)"jpegtarget" ) )
+ {
+ iCmd.Zero();
+
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::RenderL: Set EXIF data" );
+
+ // Update EXIF tags
+ UpdateExifTagsL();
+
+ // Update EXIF thumbnail
+ TPtrC8 savedexifdata = UpdateExifThumbnailL();
+
+ // Set EXIF data to target
+ iCmd.Format (_L("exifdata %d exiflen %d"), (TInt)(savedexifdata.Ptr()), savedexifdata.Length());
+
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::RenderL: EXIF data set." );
+
+
+ iCmd.Append (_L(" file \""));
+ iCmd.Append ( iTargetFile );
+ iCmd.Append (_L("\""));
+ iMainEngine->FunctionL ( n - 1, iCmd );
+ }
+
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::RenderL: Rendered" );
+}
+
+//=============================================================================
+EXPORT_C TInt CEngineWrapper::RenderBlockL()
+{
+#ifdef VERBOSE_2
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::RenderBlockL" );
+
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::RenderBlockL\tiBlock: %d", iBlock);
+ if (iTestBitmap)
+ {
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::RenderBlock\tiTestBitmap->DataAddress(): %d", (TInt)iTestBitmap->DataAddress());
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::RenderBlock\tiTestBitmap->Handle(): %d", iTestBitmap->Handle());
+ }
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::RenderBlockL\tiBuffer: %d", (TInt)iBuffer);
+#endif
+
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "RenderBlockL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ iCmd.Copy ( _L("store") );
+ TInt percentage = iMainEngine->FunctionL ( iMainEngine->NumFilters() - 1, iCmd );
+ if (percentage == 100)
+ {
+ iChangeCount = 0;
+ }
+ return percentage;
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::RenderAbortL()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::RenderAbortL" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "RenderAbort: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ iCmd.Copy ( _L("abort"));
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 1, iCmd );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::InitUndoRedo()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::InitUndoRedo" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "InitUndoRedo: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Purge undo stack
+ iUndoPoints.Reset();
+
+ // Undo
+ iPrevChangeCount = 0;
+ iChangeCount = 0;
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::AddUndoRedoStepL()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::AddUndoRedoStepL" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "AddUndoRedoStepL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Store undo point
+ TInt n = iMainEngine->NumFilters();
+ if (n > 2)
+ {
+ // Set undo point before target filter
+ iUndoPoints.Append ( n - 3 );
+ }
+
+ iPrevChangeCount = iChangeCount;
+ iChangeCount++;
+
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::AddUndoRedoStepL: iChangeCount = %d", iChangeCount);
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::AddUndoRedoStepL: iPrevChangeCount = %d", iPrevChangeCount);
+
+ // Store rotation and scale
+ User::LeaveIfError( iScaleUndoBuf.Append ( iSysPars->Scale() ) );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::UndoL()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UndoL" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "UndoL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ TBool computeBoundingRect = EFalse;
+ TBool reloadImage = EFalse;
+
+ if (iMainEngine->NumFilters() > 2)
+ {
+ TInt m = iUndoPoints.Count();
+ TInt undoindex = iUndoPoints[m-1];
+ while (iMainEngine->NumFilters() - 3 > undoindex)
+ {
+ TInt index = iMainEngine->NumFilters() - 3;
+ if ( IsSameString ( (TUint8*)iMainEngine->Filter(index)->Type(), (TUint8*) "rotate" ) )
+ {
+ computeBoundingRect = ETrue;
+ }
+ else if ( IsSameString ( (TUint8*)iMainEngine->Filter(index)->Type(), (TUint8*) "crop" ) )
+ {
+ reloadImage = ETrue;
+ }
+
+ iMainEngine->RemoveFilter (index);
+ }
+ iUndoPoints.Remove (iUndoPoints.Count() - 1);
+ }
+
+ iPrevChangeCount = iChangeCount;
+ iChangeCount--;
+
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::UndoL: iChangeCount = %d", iChangeCount);
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::UndoL: iPrevChangeCount = %d", iPrevChangeCount);
+
+ TInt count = iScaleUndoBuf.Count();
+ if ( count > 0 )
+ {
+ iSysPars->Scale() = iScaleUndoBuf[count - 1];
+ iScaleUndoBuf.Remove (count - 1);
+ }
+
+ if (reloadImage)
+ {
+ iCmd.Format( _L("ulc %d ulr %d lrc %d lrr %d"), 0,0,0,0);
+ iMainEngine->FunctionL ( 0, iCmd);
+ iMainEngine->FunctionL ( 0, _L("loadimage"));
+ for (TInt i = 0; i < iMainEngine->NumFilters(); ++i)
+ {
+ iMainEngine->FunctionL (i, _L("nop"));
+ }
+ ComputeBoundingRectL();
+ }
+
+ if ( iMainEngine->NumFilters() > 3 && computeBoundingRect && iScale == 1.0 )
+ {
+ ComputeBoundingRectL();
+ }
+ else if ( iMainEngine->NumFilters() <= 3 )
+ {
+ iBoundingRect.iTl.iX = 0;
+ iBoundingRect.iTl.iY = 0;
+ iBoundingRect.iBr.iX = iSourceSize.iWidth;
+ iBoundingRect.iBr.iY = iSourceSize.iHeight;
+ }
+ UpdateCropRectL();
+}
+
+//=============================================================================
+EXPORT_C TBool CEngineWrapper::CanUndo ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::CanUndo" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "CanUndo: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ if ( iUndoPoints.Count() > 0 )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+}
+
+//=============================================================================
+EXPORT_C TBool CEngineWrapper::IsImageChanged()
+{
+ LOGFMT2( KEngineWrapperLogFile, "CEngineWrapper::IsImageChanged: iChangeCount = %d, iPrevChangeCount = %d", iChangeCount, iPrevChangeCount );
+
+ if ( iChangeCount || (iChangeCount == 0 && iPrevChangeCount < 0))
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+}
+
+//=============================================================================
+CEngineWrapper::CEngineWrapper () :
+iScreenSize (),
+iChangeCount(0),
+iPrevChangeCount(0)
+{
+
+}
+
+//=============================================================================
+void CEngineWrapper::ConstructL ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::ConstructL" );
+
+ // Create new engine
+ iMainEngine = CFilterStack::NewL();
+
+ // Set screen size to default
+ iScreenSize.iWidth = 1;
+ iScreenSize.iHeight = 1;
+
+ // Create and initialize system parameters
+ LOG( KEngineWrapperLogFile, "CEngineWrapper: Creating system parameters" );
+ iSysPars = new (ELeave) CSystemParameters;
+}
+
+//=============================================================================
+TInt CEngineWrapper::FileExists (TDes & aFileName) const
+{
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::FileExists (TDes & aFileName: %S)", &aFileName );
+
+ TInt result = KErrNone;
+
+ RFs &fs = CEikonEnv::Static()->FsSession();
+
+ aFileName[0] = 'e';
+ if ( !BaflUtils::FileExists (fs, aFileName) )
+ {
+ aFileName[0] = 'c';
+ if ( !BaflUtils::FileExists (fs, aFileName) )
+ {
+ aFileName[0] = 'z';
+ if ( !BaflUtils::FileExists (fs, aFileName) )
+ {
+ return KErrNotFound;
+ }
+ }
+ }
+
+ if ( !BaflUtils::FileExists (fs, aFileName) )
+ {
+ result = KErrNotFound;
+ }
+
+ LOGFMT( KEngineWrapperLogFile, "\tresult: %d", result );
+
+ return result;
+}
+
+//=============================================================================
+void CEngineWrapper::Cleanup()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::Cleanup" );
+
+ // Purge undo / redo information
+ iUndoPoints.Reset();
+
+ // Delete filters
+ for ( TInt i = 0; i < iMainEngine->NumFilters(); ++i)
+ {
+ iMainEngine->RemoveFilter(i);
+ }
+
+ // Delete engine
+ if (iMainEngine)
+ {
+ delete iMainEngine;
+ iMainEngine = NULL;
+ }
+
+ // Clear rotation and scale undo buffers
+ iScaleUndoBuf.Reset();
+
+ // Delete system parameters
+ if (iSysPars)
+ {
+ delete iSysPars;
+ iSysPars = NULL;
+ }
+
+ if (iJpegComment)
+ {
+ delete iJpegComment;
+ iJpegComment = NULL;
+ }
+
+ // Delete thumbnail buffer
+ delete[] iThumb;
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::StoreZoomL ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::StoreZoom" );
+
+ iScaleSt = iScale;
+ iPanXSt = iPanX;
+ iPanYSt = iPanY;
+
+ iScale = 1.0;
+ iPanX = iSourceSize.iWidth * 0.5;
+ iPanY = iSourceSize.iHeight * 0.5;
+ UpdateCropRectL();
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::RestoreZoomL()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::RestoreZoom" );
+
+ if (iScale != iScaleSt)
+ {
+ iScale = iScaleSt;
+ iPanX = iPanXSt;
+ iPanY = iPanYSt;
+ UpdateCropRectL();
+ }
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::ZoomL (const TZoom aZoom)
+ {
+ LOGFMT( KEngineWrapperLogFile, "CEngineWrapper::ZoomL: %d", (TInt)aZoom);
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "ZoomFactor: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ if ( aZoom == EZoomMin )
+ {
+ iScale = 1.0;
+ iZoomMode = EZoomNormal;
+
+ }
+ else if ( aZoom == EZoomIn )
+ {
+
+ if ( iScale == 1.0 )
+ {
+ ComputeBoundingRectL();
+ }
+
+ if ( iZoomMode < ( ENumOfZooms - 1 ) )
+ {
+ // rescale
+ iScale *= KZoomScaleFactor;
+ // set next zoom mode
+ iZoomMode = ( TZoomMode )( ( TInt )iZoomMode + 1 );
+ }
+ }
+ else
+ {
+ if ( iZoomMode > EZoomNormal )
+ {
+ // rescale
+ iScale *= 1.0 / KZoomScaleFactor;
+ //set previous zoom mode
+ iZoomMode = ( TZoomMode )( ( TInt )iZoomMode - 1 );
+ }
+ }
+
+ UpdateCropRectL();
+ }
+
+//=============================================================================
+EXPORT_C TZoomMode CEngineWrapper::GetZoomMode()
+ {
+ return iZoomMode;
+ }
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::PanL (const TDirection aDir)
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::PanL" );
+
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "\taDir: %d", (TInt)aDir);
+#endif // VERBOSE
+
+ if (iScale == 1.0)
+ {
+ return;
+ }
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "SetPanL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ TInt angle = ComputeRotationL();
+
+ switch (aDir)
+ {
+ case EDirectionUp:
+ {
+ if (angle == 0)
+ {
+ iPanY -= iPanStep * iScale;
+ }
+ else if (angle == 90)
+ {
+ iPanX -= iPanStep * iScale;
+ }
+ else if (angle == 180)
+ {
+ iPanY += iPanStep * iScale;
+ }
+ else if (angle == 270)
+ {
+ iPanX += iPanStep * iScale;
+ }
+ break;
+ }
+ case EDirectionDown:
+ {
+ if (angle == 0)
+ {
+ iPanY += iPanStep * iScale;
+ }
+ else if (angle == 90)
+ {
+ iPanX += iPanStep * iScale;
+ }
+ else if (angle == 180)
+ {
+ iPanY -= iPanStep * iScale;
+ }
+ else if (angle == 270)
+ {
+ iPanX -= iPanStep * iScale;
+ }
+ break;
+ }
+ case EDirectionLeft:
+ {
+ if (angle == 0)
+ {
+ iPanX -= iPanStep * iScale;
+ }
+ else if (angle == 90)
+ {
+ iPanY += iPanStep * iScale;
+ }
+ else if (angle == 180)
+ {
+ iPanX += iPanStep * iScale;
+ }
+ else if (angle == 270)
+ {
+ iPanY -= iPanStep * iScale;
+ }
+ break;
+ }
+ case EDirectionRight:
+ {
+ if (angle == 0)
+ {
+ iPanX += iPanStep * iScale;
+ }
+ else if (angle == 90)
+ {
+ iPanY -= iPanStep * iScale;
+ }
+ else if (angle == 180)
+ {
+ iPanX -= iPanStep * iScale;
+ }
+ else if (angle == 270)
+ {
+ iPanY += iPanStep * iScale;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ UpdateCropRectL();
+
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::PanL( TInt aXChange, TInt aYChange )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::Pan" );
+
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "\taXChange: %d, aYChange: %d ", aXChange, aYChange );
+#endif // VERBOSE
+
+ if (iScale == 1.0)
+ {
+ return;
+ }
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "SetPanL: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ TInt angle = ComputeRotationL();
+
+ if (angle == 0)
+ {
+ // X change
+ iPanX += aXChange*(iScale/iMinScale);
+
+ // Y change
+ iPanY += aYChange*(iScale/iMinScale);
+ }
+ else if (angle == 90)
+ {
+ // X change
+ iPanX += aYChange*(iScale/iMinScale);
+
+ // Y change
+ iPanY -= aXChange*(iScale/iMinScale);
+ }
+ else if (angle == 180)
+ {
+ // X change
+ iPanX -= aXChange*(iScale/iMinScale);
+
+ // Y change
+ iPanY -= aYChange*(iScale/iMinScale);
+ }
+ else if (angle == 270)
+ {
+ // X change
+ iPanX -= aYChange*(iScale/iMinScale);
+
+ // Y change
+ iPanY += aXChange*(iScale/iMinScale);
+ }
+
+ UpdateCropRectL();
+
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::RotateL (const TRotation aRot)
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::RotateL" );
+#ifdef VERBOSE
+ LOGFMT( KEngineWrapperLogFile, "\taRot: %d", (TInt)aRot);
+#endif // VERBOSE
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "Rotation: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ // Set undo / redo point
+ AddUndoRedoStepL ();
+
+ // Add rotate filter
+ AddRotateFilterL();
+
+ // Set rotation pars
+ TBuf<128> cmd;
+ cmd.Copy (_L("angle "));
+
+ if ( ERotationCounterClockwise == aRot )
+ {
+ cmd.AppendNum (270);
+ }
+ else if ( ERotationClockwise == aRot )
+ {
+ cmd.AppendNum (90);
+ }
+ else if ( ERotation180 == aRot )
+ {
+ cmd.AppendNum (180);
+ }
+ else
+ {
+ User::Leave (KErrArgument);
+ }
+ SetParamsL (cmd);
+}
+
+//=============================================================================
+EXPORT_C CSystemParameters * CEngineWrapper::GetSystemPars ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::GetSystemPars" );
+
+ ComputeSystemParameters();
+
+ return iSysPars;
+}
+
+//=============================================================================
+void CEngineWrapper::ComputeSystemParameters ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::ComputeSystemParameters" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "GetSystemPars: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+
+ MImageFilter * filter = iMainEngine->Filter(iMainEngine->NumFilters() - 3);
+ TSize size = filter->ViewPortSize();
+ iSysPars->ViewPortRect().iTl.iX = 0;
+ iSysPars->ViewPortRect().iTl.iY = 0;
+ iSysPars->ViewPortRect().iBr.iX = size.iWidth;
+ iSysPars->ViewPortRect().iBr.iY = size.iHeight;
+
+ LOGFMT( KEngineWrapperLogFile, "ViewPortRect().iTl.iX: %d", iSysPars->ViewPortRect().iTl.iX );
+ LOGFMT( KEngineWrapperLogFile, "ViewPortRect().iTl.iY: %d", iSysPars->ViewPortRect().iTl.iY );
+ LOGFMT( KEngineWrapperLogFile, "ViewPortRect().iBr.iX: %d", iSysPars->ViewPortRect().iBr.iX );
+ LOGFMT( KEngineWrapperLogFile, "ViewPortRect().iBr.iY: %d", iSysPars->ViewPortRect().iBr.iY );
+
+ iSysPars->VisibleImageRect() = filter->Rect();
+
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRect().iTl.iX: %d", iSysPars->VisibleImageRect().iTl.iX );
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRect().iTl.iY: %d", iSysPars->VisibleImageRect().iTl.iY );
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRect().iBr.iX: %d", iSysPars->VisibleImageRect().iBr.iX );
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRect().iBr.iY: %d", iSysPars->VisibleImageRect().iBr.iY );
+
+ // Get the relative scale of the topmost filter
+ iSysPars->RelScale() = filter->Scale();
+
+ LOGFMT( KEngineWrapperLogFile, "RelScale(): %f", iSysPars->RelScale() );
+
+ TInt n = iMainEngine->NumFilters();
+ if ( n > 3 )
+ {
+
+ TRect rect;
+
+ TSize srcsize = iMainEngine->Filter(n - 3)->Rect().Size();
+ TSize tgtsize = iMainEngine->Filter(n - 1)->Rect().Size();
+
+ // Compute aspect ratio of the source
+ TInt ars = (TReal)(srcsize.iWidth << KScaleBits) / srcsize.iHeight + 0.5;
+
+ // Compute aspect ratio of the target
+ TInt art = (TReal)(tgtsize.iWidth << KScaleBits) / tgtsize.iHeight + 0.5;
+
+ // Select scale so that aspect ratio is preserved
+ if ( ars >= art )
+ {
+ TInt scale = (TReal)(tgtsize.iWidth << KScaleBits) / srcsize.iWidth + 0.5;
+ rect.iTl.iX = 0;
+ rect.iBr.iX = tgtsize.iWidth;
+ TInt h = (srcsize.iHeight * scale) >> KScaleBits;
+ rect.iTl.iY = (TReal)(tgtsize.iHeight - h) / 2 + 0.5;
+ rect.iBr.iY = (TReal)(tgtsize.iHeight + h) / 2 + 0.5;
+ }
+ else
+ {
+ TInt scale = (TReal)(tgtsize.iHeight << KScaleBits) / srcsize.iHeight + 0.5;
+ rect.iTl.iY = 0;
+ rect.iBr.iY = tgtsize.iHeight;
+ TInt w = (srcsize.iWidth * scale) >> KScaleBits;
+ rect.iTl.iX = (TReal)(tgtsize.iWidth - w) / 2 + 0.5;
+ rect.iBr.iX = (TReal)(tgtsize.iWidth + w) / 2 + 0.5;
+ }
+
+ iSysPars->VisibleImageRectPrev() = rect;
+
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRectPrev().iTl.iX: %d", iSysPars->VisibleImageRectPrev().iTl.iX );
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRectPrev().iTl.iY: %d", iSysPars->VisibleImageRectPrev().iTl.iY );
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRectPrev().iBr.iX: %d", iSysPars->VisibleImageRectPrev().iBr.iX );
+ LOGFMT( KEngineWrapperLogFile, "VisibleImageRectPrev().iBr.iY: %d", iSysPars->VisibleImageRectPrev().iBr.iY );
+ }
+}
+
+
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::GetOutputImageSize ( TInt& /*aWidth*/, TInt& /*aHeight*/ ) const
+{
+
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::SetJpegCommentL (const TDesC8& /*aComment*/)
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::SetJpegComment" );
+
+ // Check that the model is found
+ if ( !iMainEngine )
+ {
+ LOG ( KEngineWrapperLogFile, "SetJpegComment: iMainEngine not created!" );
+ User::Panic (KEnginePanic, KEnginePanicAllocation);
+ }
+}
+
+//=============================================================================
+void CEngineWrapper::AddRotateFilterL()
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::AddRotateFilterL()" );
+
+ // Add filter to engine
+ AddFilterL (KFilterRotate);
+}
+
+//=============================================================================
+TRect CEngineWrapper::ComputeViewPort (const TInt /*aStartInd*/)
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::ComputeViewPort()" );
+ return TRect();
+}
+
+//=============================================================================
+TRect CEngineWrapper::ComputeVisibleViewPort (const TRect & /*aViewPort*/)
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::ComputeVisibleViewPort()" );
+ return TRect(0,0,0,0);
+}
+
+//=============================================================================
+TPoint CEngineWrapper::ComputeNewPanValue (const TRect & /*aVvpOld*/)
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::ComputeNewPanValue()" );
+
+ return TPoint();
+}
+
+//=============================================================================
+void CEngineWrapper::CopyBufferL (TUint32 * aBuffer)
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::CopyBufferL" );
+
+ iScreenBitmap->LockHeapLC();
+
+ TSize size = iScreenBitmap->SizeInPixels();
+ TDisplayMode dmode = iScreenBitmap->DisplayMode();
+ TInt ws = iScreenBitmap->ScanLineLength (size.iWidth, dmode);
+
+ TUint8 * tpos = (TUint8*)( iScreenBitmap->DataAddress() );
+ TUint8 * tp;
+
+ for ( TInt y = 0; y < size.iHeight; y++ )
+ {
+
+ tp = tpos;
+ tpos += ws;
+
+ for ( TInt x = 0; x < size.iWidth; x++ )
+ {
+ TUint32 c = *aBuffer++;
+ *tp++ = c & 0xFF;
+ c >>= 8;
+ *tp++ = c & 0xFF;
+ c >>= 8;
+ *tp++ = c & 0xFF;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // iScreenBitmap->LockHeapLC
+}
+
+//=============================================================================
+TBool CEngineWrapper::IsSameString (
+ const TUint8 * aString1,
+ const TUint8 * aString2
+ )
+{
+ TPtrC8 s1( (TUint8*)aString1 );
+ TPtrC8 s2( (TUint8*)aString2);
+
+ if ( s1.Compare( s2 ) == 0 )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+}
+
+//=============================================================================
+void CEngineWrapper::UpdateCropRectL ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateCropRect" );
+
+ TSize screensize = iScreenSize;
+ TSize imagesize = iBoundingRect.Size();
+ TRect croprect = iBoundingRect;
+
+ if (iScale != 1.0)
+ {
+ // check rotation
+ TInt angle = ComputeRotationL();
+ TSize cropsize = imagesize;
+ TReal sw = 0.0;
+ TReal sh = 0.0;
+ if ((angle == 90) || (angle == 270))
+ {
+ cropsize.iWidth = imagesize.iWidth;
+ cropsize.iHeight = (TReal)(screensize.iWidth * imagesize.iWidth) / screensize.iHeight + 0.5;
+ TReal ari = (TReal)cropsize.iWidth / cropsize.iHeight;
+ TReal ars = (TReal)screensize.iWidth / screensize.iHeight;
+ if (ari >= ars)
+ {
+ sw = 0.5 * iScale * cropsize.iWidth;
+ sh = 0.5 * iScale * cropsize.iHeight;
+ }
+ else
+ {
+ sh = 0.5 * iScale * cropsize.iHeight;
+ sw = 0.5 * iScale * cropsize.iWidth;
+ }
+ }
+ else
+ {
+ TReal ari = (TReal)cropsize.iWidth / cropsize.iHeight;
+ TReal ars = (TReal)screensize.iWidth / screensize.iHeight;
+ if (ari >= ars)
+ {
+ sw = 0.5 * iScale * cropsize.iWidth;
+ sh = 0.5 * iScale * (cropsize.iWidth / ars);
+ }
+ else
+ {
+ sh = 0.5 * iScale * cropsize.iHeight;
+ sw = 0.5 * iScale * (cropsize.iHeight * ars);
+ }
+ }
+
+ // clip pan
+ if (iPanX - sw < iBoundingRect.iTl.iX)
+ {
+ if (iScale == 1.0)
+ {
+ iPanX = (iBoundingRect.iTl.iX + iBoundingRect.iBr.iX) / 2;
+ }
+ else
+ {
+ iPanX = iBoundingRect.iTl.iX + sw;
+ }
+ }
+ else if (iPanX + sw > iBoundingRect.iBr.iX)
+ {
+ if (iScale == 1.0)
+ {
+ iPanX = (iBoundingRect.iTl.iX + iBoundingRect.iBr.iX) / 2;
+ }
+ else
+ {
+ iPanX = iBoundingRect.iBr.iX - sw;
+ }
+ }
+ if (iPanY - sh < iBoundingRect.iTl.iY)
+ {
+ if (iScale == 1.0)
+ {
+ iPanY = (iBoundingRect.iTl.iY + iBoundingRect.iBr.iY) / 2;
+ }
+ else
+ {
+ iPanY = iBoundingRect.iTl.iY + sh;
+ }
+ }
+ else if (iPanY + sh > iBoundingRect.iBr.iY)
+ {
+ if (iScale == 1.0)
+ {
+ iPanY = (iBoundingRect.iTl.iY + iBoundingRect.iBr.iY) / 2;
+ }
+ else
+ {
+ iPanY = iBoundingRect.iBr.iY - sh;
+ }
+ }
+
+ // scale rect
+ croprect = TRect(iPanX - sw, iPanY - sh, iPanX + sw, iPanY + sh);
+ if (croprect.iTl.iX < iBoundingRect.iTl.iX)
+ {
+ croprect.iTl.iX = iBoundingRect.iTl.iX;
+ }
+ if (croprect.iTl.iY < iBoundingRect.iTl.iY)
+ {
+ croprect.iTl.iY = iBoundingRect.iTl.iY;
+ }
+ if (croprect.iBr.iX > iBoundingRect.iBr.iX)
+ {
+ croprect.iBr.iX = iBoundingRect.iBr.iX;
+ }
+ if (croprect.iBr.iY > iBoundingRect.iBr.iY)
+ {
+ croprect.iBr.iY = iBoundingRect.iBr.iY;
+ }
+
+ }
+
+ if (croprect != iOldCropRect)
+ {
+ // Update crop rectangle
+ iCmd.Format( _L("ulc %d ulr %d lrc %d lrr %d"), croprect.iTl.iX, croprect.iTl.iY,
+ croprect.iBr.iX, croprect.iBr.iY);
+ LOGDES (KEngineWrapperLogFile, iCmd);
+ iMainEngine->FunctionL ( 0, iCmd );
+ iRenderScaleBuffer = ETrue;
+ iOldCropRect = croprect;
+ }
+}
+
+
+//=============================================================================
+TPtrC8 CEngineWrapper::UpdateExifThumbnailL ()
+{
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifThumbnailL" );
+
+ // Create Jpeg encoder for memory buffer
+ MJpegSave * encoder = JpegSaveFactory::CreateJpegSaveLC (0,0);
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::0" );
+
+ // Initialize saving
+ encoder->StartSaveL (iThumbSize, TPtr8(0,0), 65536, KThumbnailJpegQuality);
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::1" );
+
+ // Save in blocks
+ TBitmapHandle bmBlock;
+ bmBlock.iData = new (ELeave) TUint32 [16 * 8];
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::2" );
+
+ for (TInt y = 0; y < iThumbSize.iHeight; y += 8)
+ {
+ for (TInt x = 0; x < iThumbSize.iWidth; x += 16)
+ {
+
+ TInt lastY = y + 8;
+ if (lastY >= iThumbSize.iHeight)
+ {
+ lastY = iThumbSize.iHeight - 1;
+ }
+ TInt lastX = x + 16;
+ if (lastX >= iThumbSize.iWidth)
+ {
+ lastX = iThumbSize.iWidth - 1;
+ }
+
+ TUint32 * pDOS = (TUint32 *)bmBlock.iData;
+ TUint32 * pSOS = iThumb + y * iThumbSize.iWidth + x;
+
+ for (TInt yy = y; yy < lastY; yy++ )
+ {
+
+ TUint32 * pD = pDOS;
+ pDOS += 16;
+
+ TUint32 * pS = pSOS;
+ pSOS += iThumbSize.iWidth;
+
+ for (TInt xx = x; xx < lastX; xx++ )
+ {
+ *pD++ = *pS++;
+ }
+ }
+
+
+ encoder->SaveBlock (bmBlock);
+ }
+ }
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::3" );
+
+ delete (TUint32 *)bmBlock.iData;
+ bmBlock.iData = NULL;
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::4" );
+
+ TPtrC8 thumbNail = encoder->Finalize();
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::5" );
+
+ TPtrC8 exif = iExifParser->SaveL (thumbNail);
+
+ LOG ( KEngineWrapperLogFile, "UpdateExifThumbnailL::6" );
+
+ CleanupStack::PopAndDestroy (); // encoder
+
+ return exif;
+}
+
+//=============================================================================
+void CEngineWrapper::UpdateExifTagsL()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL" );
+
+ // DateTime
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- DateTime" );
+ TBuf8<64> dateTimeBuf;
+ GetCurrentDateTime ( dateTimeBuf );
+ iExifParser->DeleteTag ( CExifParser::EIfd0, 0x0132);
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x0132, dateTimeBuf.PtrZ());
+
+ TInt n = iMainEngine->NumFilters();
+ MImageFilter * filter = iMainEngine->Filter(n - 2);
+
+ TInt targetWidth = (TReal)(filter->ViewPortSize().iWidth * iSysPars->Scale()) + 0.5;
+ TInt targetHeight = (TReal)(filter->ViewPortSize().iHeight * iSysPars->Scale()) + 0.5;
+
+ // ImageWidth - not needed
+ iExifParser->DeleteTag ( CExifParser::EIfd0, 0x0100);
+
+ // ImageHeight - not needed
+ iExifParser->DeleteTag ( CExifParser::EIfd0, 0x0101);
+
+ // Orientation
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x0112) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- Orientation" );
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x0112, (TUint16)1);
+ }
+
+ // EXIF version
+ TUint8 exifVersion [] = "0220";
+ if ( !iExifParser->TagExist (CExifParser::ESubIfd, 0x9000) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- ExifVersion" );
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0x9000, TPtrC8 (exifVersion));
+ }
+
+ // FlashPixVersion
+ TUint8 flashPixVersion [] = "0100";
+ if ( !iExifParser->TagExist (CExifParser::ESubIfd, 0xA000) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- FlashPixVersion" );
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA000);
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0xA000, TPtrC8 (flashPixVersion));
+ }
+
+ // ComponentsConfiguration
+ TUint8 exifComponentsConfiguration [4] = {1,2,3,0};
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- ComponentsConfiguration" );
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0x9101);
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0x9101, TPtrC8(exifComponentsConfiguration, 4));
+
+ // ColorSpace
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- ColorSpace" );
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA001);
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0xA001, (TUint16)1);
+
+ // Interoperability index
+ iExifParser->DeleteTag ( CExifParser::EInteroperability, 0x0001);
+
+ // PixelXResolution
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- PlaneXResolution" );
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA002);
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0xA002,(TUint32)targetWidth);
+
+ // PixelYResolution
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- PlaneYResolution" );
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA003);
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0xA003, (TUint32)targetHeight);
+
+ // FocalPlaneResolutionUnit
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA210);
+
+ // FocalPlaneXResolution
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA20E);
+
+ // FocalPlaneYResolution
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0xA20F);
+
+ // User Comment
+ TBuf8<256> comment;
+ TUint8 KCharCode[8] = {0x41,0x53,0x43,0x49,0x49,0x00,0x00,0x00}; // ASCII char code
+ comment.Append(TPtrC8(KCharCode, 8));
+ comment.AppendFormat(KImageEditorExifComment, my_version_major, my_version_minor, my_version_build);
+
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- UserComment" );
+ iExifParser->DeleteTag ( CExifParser::ESubIfd, 0x9286);
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0x9286, comment);
+
+ TBuf8<128> make;
+ TBuf8<128> model;
+ ImageEditorUtils::GetMakeAndModelL ( make, model );
+
+ // Make
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x010F) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- Make updated" );
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x010F, make.PtrZ());
+ }
+
+ // Model
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x0110) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- Model updated" );
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x0110, model.PtrZ());
+ }
+
+ // DateTimeOriginal
+ if ( !iExifParser->TagExist (CExifParser::ESubIfd, 0x9003) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- DateTimeOriginal updated" );
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0x9003, dateTimeBuf.PtrZ());
+ }
+
+ // DateTimeDigitized
+ if ( !iExifParser->TagExist (CExifParser::ESubIfd, 0x9004) )
+ {
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- DateTimeDigitized updated" );
+ iExifParser->AddTagL ( CExifParser::ESubIfd, 0x9004, dateTimeBuf.PtrZ());
+ }
+
+ // XResolution
+ LOG ( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- XResolution" );
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x011A) )
+ {
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x011A, (TUint32)300, (TUint32)1);
+ }
+
+ // YResolution
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- YResolution" );
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x011B) )
+ {
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x011B, (TUint32)300, (TUint32)1);
+ }
+
+ // ResolutionUnit
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- ResolutionUnit" );
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x0128) )
+ {
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x0128, (TUint16)2 );
+ }
+
+ // YCbCrPositioning
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::UpdateExifTagsL() -- YCbCrPositioning" );
+ if ( !iExifParser->TagExist (CExifParser::EIfd0, 0x0213) )
+ {
+ iExifParser->AddTagL ( CExifParser::EIfd0, 0x0213, (TUint16)1 );
+ }
+
+
+}
+
+//=============================================================================
+void CEngineWrapper::GetCurrentDateTime (TDes8 & aDateTimeBuf) const
+{
+ // Time in microseconds since 0 AD nominal Gregorian
+ TTime time;
+ // year-month-day-hour-minute-second-microsecond
+ TDateTime dateTime;
+
+ // Get current local time
+ time.HomeTime();
+
+ // Convert to fields
+ dateTime = time.DateTime();
+
+ // Create descriptors for the components.
+ // This is needed because the leading zeros
+ // cannotbe suppressed.
+ TBuf8<2> month;
+ TBuf8<2> day;
+ TBuf8<2> hour;
+ TBuf8<2> minute;
+ TBuf8<2> second;
+
+ if( TInt(dateTime.Month()) < 9 )
+ {
+ month.AppendNum( 0 );
+ }
+ month.AppendNum( TInt(dateTime.Month()+1) );
+
+ if( dateTime.Day() < 9 )
+ {
+ day.AppendNum( 0 );
+ }
+ day.AppendNum( dateTime.Day()+1 );
+
+ if( dateTime.Hour() < 10 )
+ {
+ hour.AppendNum( 0 );
+ }
+ hour.AppendNum( dateTime.Hour() );
+
+ if( dateTime.Minute() < 10 )
+ {
+ minute.AppendNum( 0 );
+ }
+ minute.AppendNum( dateTime.Minute() );
+
+ if( dateTime.Second() < 10 )
+ {
+ second.AppendNum( 0 );
+ }
+ second.AppendNum( dateTime.Second() );
+
+ // Format the time to the format
+ // "YYYY:MM:DD HH:MM:SS"
+ _LIT8(KFormatTxt,"%d:%S:%S %S:%S:%S");
+ aDateTimeBuf.Format(
+ KFormatTxt,
+ dateTime.Year(),
+ &month,
+ &day,
+ &hour,
+ &minute,
+ &second
+ );
+}
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::SetBitmap (CFbsBitmap * aBitmap)
+{
+ iScreenBitmap = aBitmap;
+}
+
+
+//=============================================================================
+EXPORT_C void CEngineWrapper::CreateExifThumbNailL ()
+{
+ LOG( KEngineWrapperLogFile, "CEngineWrapper::CreateExifThumbNailL" );
+
+#ifdef EXIF_SUPPORT
+
+ // Delete old thumbnail
+ delete[] iThumb;
+ iThumb = NULL;
+
+ // Re-load the zoomed image if needed
+ if ( iRenderScaleBuffer )
+ {
+ iMainEngine->FunctionL ( 0, _L("loadimage"));
+ iRenderScaleBuffer = EFalse;
+ }
+ for ( TInt i = 0; i < iMainEngine->NumFilters(); ++i)
+ {
+ iMainEngine->FunctionL (i, _L("nop"));
+ }
+
+ TReal scale = 1.0;
+ TSize imagesize = iMainEngine->Filter(iMainEngine->NumFilters() - 3)->Rect().Size();
+ if (imagesize.iWidth > imagesize.iHeight)
+ {
+ scale = (TReal)imagesize.iWidth / KThumbnailMaxDimension;
+ }
+ else
+ {
+ scale = (TReal)imagesize.iHeight / KThumbnailMaxDimension;
+ }
+
+ // Crete new thumbnail
+ iThumbSize.iWidth = (TInt)((imagesize.iWidth / scale) + 0.5);
+ iThumbSize.iHeight = (TInt)((imagesize.iHeight / scale) + 0.5);
+
+ // Just ensure that dimension are never 0
+ if (iThumbSize.iWidth == 0)
+ {
+ iThumbSize.iWidth = 1;
+ }
+ if (iThumbSize.iHeight == 0)
+ {
+ iThumbSize.iHeight = 1;
+ }
+
+ LOGFMT( KEngineWrapperLogFile, "iThumbSize.iWidth = %d", iThumbSize.iWidth);
+ LOGFMT( KEngineWrapperLogFile, "iThumbSize.iHeight = %d", iThumbSize.iHeight);
+
+ iThumb = new (ELeave) TUint32 [iThumbSize.iWidth * iThumbSize.iHeight];
+
+ // Set thumbnail size to buffer filter
+ iCmd.Format( _L("width %d height %d"), iThumbSize.iWidth, iThumbSize.iHeight);
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 1, iCmd );
+ iMainEngine->FunctionL ( iMainEngine->NumFilters() - 2, _L("nop"));
+
+ // Copy data to the new thumbnail
+ TUint32 * pBuffer = (TUint32 *)iMainEngine->FunctionL (iMainEngine->NumFilters() - 1, _L("getbitmap"));
+ Mem::Copy (iThumb, pBuffer, iThumbSize.iWidth * iThumbSize.iHeight * sizeof(TUint32));
+
+ LOG( KEngineWrapperLogFile, "EXIF thumbnail created!" );
+
+#endif
+}
+
+
+//=============================================================================
+TInt CEngineWrapper::ComputeRotationL ()
+{
+
+ TInt angle = 0;
+ TInt ind = 0;
+ while ( ind < iMainEngine->NumFilters() )
+ {
+ MImageFilter * filter = iMainEngine->Filter(ind);
+ char * cmpstr = "rotate";
+ TPtrC8 type ( (const TUint8 *)filter->Type() );
+ TPtrC8 typecmp ((const TUint8 *)cmpstr);
+ if ( type == typecmp )
+ {
+ angle += filter->CmdL(_L("getangle"));
+ }
+ ind++;
+ }
+ angle %= 360;
+ return angle;
+}
+
+
+//=============================================================================
+void CEngineWrapper::ComputeBoundingRectL()
+{
+ MImageFilter * pFilter = iMainEngine->Filter(iMainEngine->NumFilters() - 3);
+ TReal relscale = pFilter->Scale();
+ TRect rect = pFilter->Rect();
+ TSize size = iMainEngine->Filter(0)->ViewPortSize();
+ rect.iTl.iX = (TInt)((rect.iTl.iX / relscale) + 0.5);
+ rect.iTl.iY = (TInt)((rect.iTl.iY / relscale) + 0.5);
+ rect.iBr.iX = (TInt)((rect.iBr.iX / relscale) + 0.5);
+ rect.iBr.iY = (TInt)((rect.iBr.iY / relscale) + 0.5);
+ TInt angle = ComputeRotationL();
+
+ if (angle == 90 || angle == 270)
+ {
+ iBoundingRect.iTl.iX = rect.iTl.iY;
+ iBoundingRect.iTl.iY = rect.iTl.iX;
+ iBoundingRect.iBr.iX = rect.iBr.iY;
+ iBoundingRect.iBr.iY = rect.iBr.iX;
+ }
+ else
+ {
+ iBoundingRect = rect;
+ }
+
+ size = iBoundingRect.Size();
+ iPanX = (iBoundingRect.iTl.iX + iBoundingRect.iBr.iX) / 2;
+ iPanY = (iBoundingRect.iTl.iY + iBoundingRect.iBr.iY) / 2;
+}
+
+
+// End of File