--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditorengine/filters/FilterCartoon/Src/CFilterCartoon.cpp Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,462 @@
+/*
+* 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 <e32math.h>
+#include "CFilterCartoon.h"
+
+const TInt KMaxColors = 10;
+const TInt KColorBits = 8;
+
+const TUint8 ByteMask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
+
+/*
+*
+* CLASS: CFilterCartoon
+*
+*/
+
+//=============================================================================
+EXPORT_C TInt CFilterCartoon::Create()
+ {
+ CFilterCartoon* ptr = NULL;
+ TRAPD( error, ptr = NewL(); );
+ if( error != KErrNone )
+ {
+ ptr = NULL;
+ }
+ return (TInt)((MImageFilter*)ptr);
+ }
+
+//=============================================================================
+CFilterCartoon* CFilterCartoon::NewL()
+ {
+ CFilterCartoon* self = new( ELeave )CFilterCartoon();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+//=============================================================================
+CFilterCartoon::~CFilterCartoon()
+{
+ delete[] i16BitIndLut;
+ delete[] iRGB;
+}
+
+//=============================================================================
+CFilterCartoon::CFilterCartoon()
+ {
+
+ }
+
+//=============================================================================
+void CFilterCartoon::ConstructL()
+ {
+
+ }
+
+//=============================================================================
+TRect CFilterCartoon::Rect()
+ {
+ return iChild->Rect();
+ }
+
+//=============================================================================
+TReal CFilterCartoon::Scale()
+ {
+ return iChild->Scale();
+ }
+
+//=============================================================================
+TSize CFilterCartoon::ViewPortSize()
+{
+ return iChild->ViewPortSize();
+}
+
+//=============================================================================
+TBlock * CFilterCartoon::GetBlockL ( const TRect & aRect )
+{
+ TBlock * pB = iChild->GetBlockL (aRect);
+ if (!pB)
+ {
+ return NULL;
+ }
+
+ TUint32 * pD = pB->iData;
+ TUint32 c = 0;
+ TUint32 r,g,b;
+ for (TInt i = pB->iDataLength; i != 0 ; --i)
+ {
+ c = *pD;
+ b = c & 0xFF;
+ c >>= 8;
+ g = c & 0xFF;
+ c >>= 8;
+ r = c & 0xFF;
+ c = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+ *pD++ = iRGB[i16BitIndLut[c]];
+
+ }
+ return pB;
+}
+
+
+//=============================================================================
+void CFilterCartoon::SetParent( MImageFilter* aParent )
+ {
+ iParent = aParent;
+ }
+
+//=============================================================================
+void CFilterCartoon::SetChild( MImageFilter* aChild )
+ {
+ iChild = aChild;
+ }
+
+//=============================================================================
+TInt CFilterCartoon::CmdL( const TDesC16& aCmd )
+{
+
+ TLex lex (aCmd);
+
+ while ( !lex.Eos() )
+ {
+ TPtrC token = lex.NextToken();
+ if( token.Compare( _L("quantcolors") ) == 0 )
+ {
+ CreateOctreePaletteL();
+ }
+ }
+ return 0;
+}
+
+//=============================================================================
+const char* CFilterCartoon::Type()
+ {
+ return "cartoon";
+ }
+
+//=============================================================================
+void CFilterCartoon::CreateOctreePaletteL()
+{
+
+ // Create new quantizer
+ COTreeQuant * quant = new (ELeave) COTreeQuant;
+ CleanupStack::PushL( quant );
+
+ // Octree quantize colors
+ TRect rect = iChild->Rect();
+ TBlock * pB = iChild->GetBlockL(rect);
+ TUint32 * pD = pB->iData;
+ TInt i;
+ for (i = 0; i < pB->iDataLength; ++i, pD++)
+ {
+ quant->AddColorL (*pD);
+ while ( quant->iLeaves > KMaxColors )
+ {
+ quant->ReduceTree ();
+ }
+ }
+
+ delete pB;
+ pB = NULL;
+
+ // Create palette
+ quant->GetColorTable();
+
+ // Get new iCount
+ iCount = quant->iPalette.Count();
+
+ // Create 16 bit indexing array
+ delete[] i16BitIndLut;
+ i16BitIndLut = NULL;
+ i16BitIndLut = new (ELeave) TInt [65536];
+
+ delete[] iRGB;
+ iRGB = NULL;
+ iRGB = new (ELeave) TUint32 [iCount];
+
+
+ // Enumerate indexing array
+ for (i = 0; i < 65536; ++i)
+ {
+ TUint32 c = i;
+ TUint32 b = c & 0x1F;
+ c >>= 5;
+ TUint32 g = c & 0x3F;
+ c >>= 6;
+ TUint32 r = c & 0x1F;
+
+ TInt md = 99999999;
+
+ for (TInt j = 0; j < iCount; ++j)
+ {
+ c = quant->iPalette[j];
+ TUint32 bb = c & 0xFF;
+ bb >>= 3;
+
+ c >>= 8;
+ TUint32 gg = c & 0xFF;
+ gg >>= 2;
+
+ c >>= 8;
+ TUint32 rr = c & 0xFF;
+ rr >>= 3;
+
+ TInt d = (b-bb) * (b-bb) + (g-gg) * (g-gg) + (r-rr) * (r-rr);
+ if (d < md)
+ {
+ md = d;
+ i16BitIndLut[i] = j;
+ }
+ else if (d == md)
+ {
+/*
+ // compute i in 24 bit coordinates
+ c = i;
+ b = (c & 0x1F) << 3;
+ c >>= 5;
+ g = (c & 0x3F) << 2;
+ c >>= 6;
+ r = (c & 0x1F) << 3;
+
+ // compute distance of old min to i
+ c = iRGB[i16BitIndLut[i]];
+ bb = (c & 0xFF);
+ c >>= 8;
+ gg = (c & 0xFF);
+ c >>= 8;
+ rr = (c & 0xFF);
+ d = (b-bb) * (b-bb) + (g-gg) * (g-gg) + (r-rr) * (r-rr);
+
+ // compute distance of the new min to i
+ c = iRGB[j];
+ bb = (c & 0xFF);
+ c >>= 8;
+ gg = (c & 0xFF);
+ c >>= 8;
+ rr = (c & 0xFF);
+ TInt d2 = (b-bb) * (b-bb) + (g-gg) * (g-gg) + (r-rr) * (r-rr);
+
+ if (d2 < d)
+ {
+ i16BitIndLut[i] = j;
+ }
+*/
+ }
+ }
+
+ }
+
+ for (TInt j = 0; j < iCount; ++j)
+ {
+ iRGB[j] = quant->iPalette[j];
+ }
+
+ CleanupStack::PopAndDestroy( quant );
+}
+
+
+/*
+*
+* CLASS: CNode
+*
+*/
+
+//=============================================================================
+CNode::CNode()
+{
+
+}
+
+//=============================================================================
+CNode::~CNode()
+{
+ for (TInt i = 0; i < 8; i++)
+ {
+ delete iChild[i];
+ iChild[i] = NULL;
+ }
+ iNext = NULL;
+}
+
+/*
+*
+* CLASS: COTreeQuant
+*
+*/
+
+//=============================================================================
+COTreeQuant::COTreeQuant()
+{
+
+}
+
+//=============================================================================
+COTreeQuant::~COTreeQuant()
+{
+ delete iTree;
+ iTree = NULL;
+ Mem::FillZ(iReducibleNodes, 9 * sizeof(CNode *));
+ iPalette.Reset();
+}
+
+//=============================================================================
+void COTreeQuant::AddColorL (TUint32 aRgb)
+{
+ DoAddColorL (&iTree, aRgb, 0);
+}
+
+//=============================================================================
+void COTreeQuant::ReduceTree ()
+{
+
+ // Find the deepest level with at least 1 reducible node
+ TInt i=0;
+ for (i = KColorBits - 1; (i > 0) && (!iReducibleNodes[i]); i--) {};
+
+ // Reduce most recent node at level i
+ CNode * pNode = iReducibleNodes[i];
+ iReducibleNodes[i] = pNode->iNext;
+
+ TInt reds = 0;
+ TInt greens = 0;
+ TInt blues = 0;
+ TInt children = 0;
+
+ for ( i = 0; i < 8; i++)
+ {
+ if ( pNode->iChild[i] )
+ {
+ reds += pNode->iChild[i]->iRedSum;
+ greens += pNode->iChild[i]->iGreenSum;
+ blues += pNode->iChild[i]->iBlueSum;
+ pNode->iPixels += pNode->iChild[i]->iPixels;
+ delete pNode->iChild[i];
+ pNode->iChild[i] = NULL;
+ children++;
+ }
+ }
+
+ pNode->iIsLeaf = ETrue;
+ pNode->iRedSum = reds;
+ pNode->iGreenSum = greens;
+ pNode->iBlueSum = blues;
+ iLeaves -= (children - 1);
+}
+
+//=============================================================================
+void COTreeQuant::GetColorTable ()
+{
+ GetPaletteColors ( *iTree );
+}
+
+//=============================================================================
+TInt COTreeQuant::GetColorCount() const
+{
+ return iLeaves;
+}
+
+//=============================================================================
+void COTreeQuant::DoAddColorL (CNode ** apNode, TUint32 aRgb, TInt aLevel)
+{
+
+ // If node does not exist, create new
+ if (!*apNode)
+ {
+ *apNode = new (ELeave) CNode;
+
+ (*apNode)->iIsLeaf = (aLevel == KColorBits) ? ETrue : EFalse;
+ if ((*apNode)->iIsLeaf)
+ {
+ iLeaves++;
+ }
+ else
+ {
+ (*apNode)->iNext = iReducibleNodes[aLevel];
+ iReducibleNodes[aLevel] = *apNode;
+ }
+ }
+
+ TUint32 c = aRgb;
+ TUint8 b = (TUint8)(c & 0xFF);
+ c >>= 8;
+ TUint8 g = (TUint8)(c & 0xFF);
+ c >>= 8;
+ TUint8 r = (TUint8)(c & 0xFF);
+
+ // Update colors if leaf
+ if ( (*apNode)->iIsLeaf )
+ {
+ (*apNode)->iPixels++;
+ (*apNode)->iRedSum += r;
+ (*apNode)->iGreenSum += g;
+ (*apNode)->iBlueSum += b;
+ }
+
+ // Recurse deeper if not a leaf
+ else
+ {
+
+ TInt shift = 7 - aLevel;
+ TInt index = (((r & ByteMask[aLevel]) >> shift) << 2) |
+ (((g & ByteMask[aLevel]) >> shift) << 1) |
+ ((b & ByteMask[aLevel]) >> shift);
+
+ DoAddColorL (&((*apNode)->iChild[index]), aRgb, aLevel + 1);
+ }
+
+}
+
+//=============================================================================
+void COTreeQuant::GetPaletteColors ( const CNode & aNode )
+{
+ if ( aNode.iIsLeaf )
+ {
+ TUint8 r = (TUint8) (aNode.iRedSum / aNode.iPixels);
+ TUint8 g = (TUint8) (aNode.iGreenSum / aNode.iPixels);
+ TUint8 b = (TUint8) (aNode.iBlueSum / aNode.iPixels);
+ iPalette.Append ( ((r << 16) | (g << 8) | b) );
+ }
+ else
+ {
+ for (TInt i = 0; i < 8; i++)
+ {
+ if ( aNode.iChild[i] )
+ {
+ GetPaletteColors ( *aNode.iChild[i] );
+ }
+ }
+ }
+}
+
+
+/*
+*
+* ENTRY POINT
+*
+*/
+//=============================================================================
+#if !defined(EKA2)
+GLDEF_C TInt E32Dll( TDllReason )
+ {
+ return KErrNone;
+ }
+#endif