--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditorengine/filters/FilterJpegSource/Src/CFilterJpegSource.cpp Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,532 @@
+/*
+* 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:
+*
+*/
+
+
+#include <fbs.h>
+#include "CFilterJpegSource.h"
+#include "JpegLoadFactory.h"
+#include "MJpegLoad.h"
+
+const TInt KBlockBufferSize = 256; // should be enough for every picture...
+const TInt KScaleBits = 12;
+const TInt KDestBufferMaxDim = 352;
+
+//=============================================================================
+EXPORT_C TInt CFilterJpegSource::Create()
+ {
+ CFilterJpegSource* ptr = NULL;
+ TRAPD( error, ptr = NewL(); );
+ if( error != KErrNone )
+ {
+ ptr = NULL;
+ }
+ return (TInt)((MImageFilter*)ptr);
+ }
+
+//=============================================================================
+CFilterJpegSource* CFilterJpegSource::NewL()
+ {
+ CFilterJpegSource* self = new( ELeave )CFilterJpegSource();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+//=============================================================================
+CFilterJpegSource::~CFilterJpegSource()
+{
+ delete iJpeg;
+ delete iDestBuffer;
+ delete[] iIndexMap;
+ if ( iBlockBuffer )
+ {
+ for (TInt i = 0; i < KBlockBufferSize; ++i)
+ {
+ delete iBlockBuffer[i];
+ iBlockBuffer[i] = NULL;
+ }
+ }
+ delete[] iBlockBuffer;
+ iBlockBuffer = NULL;
+}
+
+//=============================================================================
+CFilterJpegSource::CFilterJpegSource()
+ {
+
+ }
+
+//=============================================================================
+void CFilterJpegSource::ConstructL()
+ {
+
+ }
+
+//=============================================================================
+TRect CFilterJpegSource::Rect()
+{
+ if (iOutputState == EDirect)
+ {
+ return iRect;
+ }
+ else
+ {
+ return iScaledRect;
+ }
+}
+
+//=============================================================================
+TReal CFilterJpegSource::Scale()
+{
+ if (iOutputState == EDirect)
+ {
+ return 1.0;
+ }
+ else
+ {
+ return iRelScale;
+ }
+}
+
+//=============================================================================
+TSize CFilterJpegSource::ViewPortSize()
+{
+ return iFullSize;
+}
+
+//=============================================================================
+TBlock * CFilterJpegSource::GetBlockL ( const TRect & aRect )
+{
+ if (iOutputState == EBuffer)
+ {
+ if ( !aRect.Intersects(iScaledRect) )
+ {
+ return NULL;
+ }
+ TRect rect = aRect;
+ rect.Intersection(iScaledRect);
+
+ TBlock * pB = new (ELeave) TBlock (rect);
+
+ TUint32 * pS = iDestBuffer + (rect.iTl.iY - iScaledRect.iTl.iY) * iDestSize.iWidth +
+ (rect.iTl.iX - iScaledRect.iTl.iX);
+ TUint32 * pD = pB->iData;
+
+ for (TInt i = rect.iTl.iY; i < rect.iBr.iY; ++i)
+ {
+ Mem::Copy(pD, pS, pB->iWidth * sizeof(TUint32));
+ pD += pB->iWidth;
+ pS += iDestSize.iWidth;
+ }
+ return pB;
+ }
+ else
+ {
+
+ if (!aRect.Intersects(iRect))
+ {
+ return NULL;
+ }
+
+ // Clip rectangle to image
+ TRect rect = aRect;
+ rect.Intersection(iRect);
+
+ // Compute region of interest in blocks
+ TRect blockRect = rect;
+ blockRect.iTl.iX /= iBlockSize.iWidth;
+ blockRect.iTl.iY /= iBlockSize.iHeight;
+ blockRect.iBr.iX /= iBlockSize.iWidth;
+ blockRect.iBr.iY /= iBlockSize.iHeight;
+
+ if (blockRect.iBr.iX < iSizeInBlocks.iWidth)
+ {
+ blockRect.iBr.iX++;
+ }
+ if (blockRect.iBr.iY < iSizeInBlocks.iHeight)
+ {
+ blockRect.iBr.iY++;
+ }
+
+ // Create block for pixel data
+ TBlock * pB = new (ELeave) TBlock;
+ CleanupStack::PushL(pB);
+ pB->iRect = blockRect;
+ pB->iRect.iTl.iX *= iBlockSize.iWidth;
+ pB->iRect.iTl.iY *= iBlockSize.iHeight;
+ pB->iRect.iBr.iX *= iBlockSize.iWidth;
+ pB->iRect.iBr.iX += iBlockSize.iWidth;
+ pB->iRect.iBr.iY *= iBlockSize.iHeight;
+ pB->iRect.iBr.iY += iBlockSize.iHeight;
+ pB->iWidth = (pB->iRect.iBr.iX - pB->iRect.iTl.iX);
+ pB->iHeight = (pB->iRect.iBr.iY - pB->iRect.iTl.iY);
+ pB->iDataLength = pB->iWidth * pB->iHeight;
+ pB->iData = new (ELeave) TUint32 [pB->iDataLength];
+
+ // Read all blocks in region of interest
+ for (TInt i = blockRect.iTl.iY; i < blockRect.iBr.iY; ++i)
+ {
+
+ for (TInt j = blockRect.iTl.iX; j < blockRect.iBr.iX; ++j)
+ {
+
+ // Get block index
+ TInt index = i * iSizeInBlocks.iWidth + j;
+
+ // If not found, load new block, add to cache and update index table
+ if ( iIndexMap[index] < 0 )
+ {
+
+ // Load block
+ TBlockEntry * e = new (ELeave) TBlockEntry;
+ CleanupStack::PushL(e);
+ e->iRect = TRect ( TPoint (j * iBlockSize.iWidth, i * iBlockSize.iHeight), iBlockSize);
+ e->iBitmap = iJpeg->LoadBlockL (TPoint(j,i));
+
+ // Remove index of the oldest block from the map
+ if (iBlockBuffer [iOldestBlock])
+ {
+ TPoint blockPos = iBlockBuffer[iOldestBlock]->iRect.iTl;
+ blockPos.iX /= iBlockSize.iWidth;
+ blockPos.iY /= iBlockSize.iHeight;
+ iIndexMap[blockPos.iY * iSizeInBlocks.iWidth + blockPos.iX] = -1;
+
+ // Delete oldest block
+ delete iBlockBuffer [iOldestBlock];
+ iBlockBuffer [iOldestBlock] = NULL;
+ }
+
+ // Insert new block to buffer and update map
+ iBlockBuffer[iOldestBlock] = e;
+ iIndexMap[index] = iOldestBlock;
+ CleanupStack::Pop(e);
+
+ // Update old block index
+ iOldestBlock++;
+ if (iOldestBlock >= KBlockBufferSize) iOldestBlock = 0;
+
+ }
+
+ // Store pixel data to block
+ TUint32 * pS = (TUint32*)( iBlockBuffer[ iIndexMap[index] ]->iBitmap.iData );
+ TUint32 * pD =
+ pB->iData +
+ (i - blockRect.iTl.iY) * iBlockSize.iHeight * pB->iWidth +
+ (j - blockRect.iTl.iX) * iBlockSize.iWidth;
+ for (TInt ib = 0; ib < iBlockSize.iHeight; ++ib)
+ {
+ Mem::Copy (pD, pS, iBlockSize.iWidth * sizeof(TUint32));
+ pS += iBlockSize.iWidth;
+ pD += pB->iWidth;
+ }
+ }
+ }
+ CleanupStack::Pop( pB );
+ return pB;
+ }
+}
+
+
+//=============================================================================
+void CFilterJpegSource::SetParent( MImageFilter* aParent )
+ {
+ iParent = aParent;
+ }
+
+//=============================================================================
+void CFilterJpegSource::SetChild( MImageFilter* aChild )
+ {
+ iChild = aChild;
+ }
+
+//=============================================================================
+TInt CFilterJpegSource::CmdL( const TDesC16& aCmd )
+ {
+
+ TLex lex( aCmd );
+
+ while( ! lex.Eos() )
+ {
+
+ TPtrC token = lex.NextToken();
+ if( token.Compare( _L("file") ) == 0 )
+ {
+ iFileName.Zero();
+
+ // Find the start of the string
+ while (!lex.Eos())
+ {
+ if (lex.Get() == '"') break;
+ }
+
+ // Get the text data
+ while (!lex.Eos())
+ {
+ TChar c= lex.Get();
+ if (c == '"')
+ {
+ break;
+ }
+ else
+ {
+ iFileName.Append(c);
+ }
+ }
+ }
+ else if( token.Compare( _L("loadimage") ) == 0 )
+ {
+
+ delete iJpeg;
+ iJpeg = 0;
+ iJpeg = JpegLoadFactory::CreateJpegLoadL();
+
+ // open
+ iJpeg->OpenL( iFileName );
+ iJpeg->ScanRandomL();
+
+ const TJpegData & d = iJpeg->Info();
+
+ // set crop rectangle to full image size
+ if (iRect.Size() == TSize(0,0))
+ {
+ iRect.iTl.iX = 0;
+ iRect.iTl.iY = 0;
+ iRect.iBr.iX = d.iSize.iWidth;
+ iRect.iBr.iY = d.iSize.iHeight;
+ }
+ iFullSize = d.iSize;
+
+ // set macroblock parameters
+ iBlockSize = d.iBlockSize;
+ iSizeInBlocks = d.iSizeInBlocks;
+
+ iOutputState = EBuffer;
+
+ if ( iBlockBuffer )
+ {
+ for (TInt i = 0; i < KBlockBufferSize; ++i)
+ {
+ delete iBlockBuffer[i];
+ iBlockBuffer[i] = NULL;
+ }
+ }
+ delete[] iBlockBuffer;
+ iBlockBuffer = NULL;
+ iBlockBuffer = new (ELeave) TBlockEntry * [KBlockBufferSize];
+ TInt i;
+ for (i = 0; i < KBlockBufferSize; ++i) iBlockBuffer[i] = NULL;
+
+ iSizeInBlocks = d.iSizeInBlocks;
+ TInt blocks = iSizeInBlocks.iWidth * iSizeInBlocks.iHeight;
+ delete[] iIndexMap;
+ iIndexMap = NULL;
+ iIndexMap = new (ELeave) TInt [blocks];
+ for (i = 0; i < blocks; ++i) iIndexMap[i] = -1;
+
+ iOldestBlock = 0;
+
+
+ // load rectangle
+ LoadRectL();
+ }
+ else if( token.Compare( _L("exifdata") ) == 0 )
+ {
+ return (TInt)(iJpeg->ExifData().Ptr());
+ }
+ else if( token.Compare( _L("ulc") ) == 0 )
+ {
+ lex.Inc();
+ lex.Val( iRect.iTl.iX );
+ }
+ else if( token.Compare( _L("ulr") ) == 0 )
+ {
+ lex.Inc();
+ lex.Val( iRect.iTl.iY );
+ }
+ else if( token.Compare( _L("lrc") ) == 0 )
+ {
+ lex.Inc();
+ lex.Val( iRect.iBr.iX );
+ }
+ else if( token.Compare( _L("lrr") ) == 0 )
+ {
+ lex.Inc();
+ lex.Val( iRect.iBr.iY );
+ }
+ else if( token.Compare( _L("fileoutput") ) == 0 )
+ {
+ iRect.iTl.iX = 0;
+ iRect.iTl.iY = 0;
+ iRect.iBr.iX = iFullSize.iWidth;
+ iRect.iBr.iY = iFullSize.iHeight;
+ iOutputState = EDirect;
+ }
+ else if( token.Compare( _L("bufferoutput") ) == 0 )
+ {
+ iOutputState = EBuffer;
+ }
+ else if( token.Compare( _L("exiflength") ) == 0 )
+ {
+ return iJpeg->ExifData().Length();
+ }
+ }
+ return 0;
+ }
+
+//=============================================================================
+const char* CFilterJpegSource::Type()
+ {
+ return "jpegsource";
+ }
+
+//=============================================================================
+void CFilterJpegSource::LoadRectL()
+ {
+
+ // compute destination buffer size
+ TInt width = iRect.iBr.iX - iRect.iTl.iX;
+ TInt height = iRect.iBr.iY - iRect.iTl.iY;
+
+ if (width >= height)
+ {
+ TReal scale = (TReal)KDestBufferMaxDim / width;
+ iDestSize.iWidth = KDestBufferMaxDim;
+ iDestSize.iHeight = (TInt)(height * scale + 0.5);
+ }
+ else
+ {
+ TReal scale = (TReal)KDestBufferMaxDim / height;
+ iDestSize.iHeight = KDestBufferMaxDim;
+ iDestSize.iWidth = (TInt)(width * scale + 0.5);
+ }
+
+ // create new destination buffer
+ delete[] iDestBuffer;
+ iDestBuffer = new (ELeave) TUint32 [iDestSize.iWidth * iDestSize.iHeight];
+
+ // compute scale
+ TJpegScale scale = EScale1;
+ while ((width /= 2) > iDestSize.iWidth)
+ {
+ if (scale == EScale1)
+ {
+ scale= EScale2;
+ }
+ else if (scale == EScale2)
+ {
+ scale= EScale4;
+ }
+ else if (scale == EScale4)
+ {
+ scale= EScale8;
+ }
+ }
+
+ // load scaled rectangle
+ TBitmapHandle loadbitmap;
+ TRect loadrect = iRect;
+ iJpeg->SetScale(scale);
+ loadbitmap = iJpeg->LoadImageL(loadrect);
+
+ // scale buffer
+ TInt sc = (TInt) ((TReal)(height << KScaleBits) / iDestSize.iHeight + 0.5);
+ TInt ws = (loadrect.iBr.iX - loadrect.iTl.iX) >> (TInt)scale;
+
+ TUint32 * pD = iDestBuffer;
+ TUint32 * pS = (TUint32 *)loadbitmap.iData +
+ ((iRect.iTl.iY - loadrect.iTl.iY) >> (TInt)scale) * ws +
+ ((iRect.iTl.iX - loadrect.iTl.iX) >> (TInt)scale);
+
+ for (TInt i = 0; i < iDestSize.iHeight; ++i)
+ {
+ TInt y = (i * sc) >> KScaleBits;
+ y >>= (TInt)scale;
+ for (TInt j = 0; j < iDestSize.iWidth; ++j)
+ {
+ TInt x = (j * sc) >> KScaleBits;
+ x >>= (TInt)scale;
+ *pD++ = *(pS + y * ws + x);
+ }
+ }
+
+ delete loadbitmap.iData;
+
+ iRelScale = (TReal)(iDestSize.iHeight) / (TReal)height;
+
+ iScaledRect.iTl.iX = (TInt)(iRelScale * iRect.iTl.iX + 0.5);
+ iScaledRect.iTl.iY = (TInt)(iRelScale * iRect.iTl.iY + 0.5);
+ iScaledRect.iBr.iX = (TInt)(iRelScale * iRect.iBr.iX + 0.5);
+ iScaledRect.iBr.iY = (TInt)(iRelScale * iRect.iBr.iY + 0.5);
+
+ // check that iScaledRect is inside buffer
+ TInt tmp = iScaledRect.iBr.iX - iScaledRect.iTl.iX - iDestSize.iWidth;
+ if ( tmp > 0 )
+ {
+ iScaledRect.iBr.iX -= tmp;
+ }
+
+ tmp = iScaledRect.iBr.iY - iScaledRect.iTl.iY - iDestSize.iHeight;
+ if (tmp > 0 )
+ {
+ iScaledRect.iBr.iY -= tmp;
+ }
+
+
+// CFbsBitmap * bitmap = new (ELeave) CFbsBitmap;
+// CleanupStack::PushL(bitmap);
+// User::LeaveIfError(bitmap->Create(iDestSize, EColor16M));
+// TBitmapUtil bm (bitmap);
+// bm.Begin(TPoint(0,0));
+// TUint8 * pDOS = (TUint8 *)bitmap->DataAddress();
+// pS = iDestBuffer;
+// ws = CFbsBitmap::ScanLineLength(iDestSize.iWidth, EColor16M);
+// for (TInt ii = 0; ii < iDestSize.iHeight; ++ii)
+// {
+// TUint8 * pD = pDOS;
+// pDOS += ws;
+// for (TInt j = 0; j < iDestSize.iWidth; ++j)
+// {
+// TUint32 c = *pS++;
+// *pD++ = c & 0xFF;
+// c >>= 8;
+// *pD++ = c & 0xFF;
+// c >>= 8;
+// *pD++ = c & 0xFF;
+// }
+// }
+// bm.End();
+// TFileName filename;
+// filename.Copy (_L("c:\\nokia\\images\\sf_"));
+// filename.AppendNum((TInt)iDestBuffer);
+// filename.Append(_L(".mbm"));
+// bitmap->Save(filename);
+//
+// CleanupStack::PopAndDestroy(); // bitmap
+
+
+ }
+
+
+
+#if !defined(EKA2)
+GLDEF_C TInt E32Dll( TDllReason )
+ {
+ return KErrNone;
+ }
+#endif