imageeditorengine/filters/FilterSharpness/Src/CFilterSharpness.cpp
changeset 1 edfc90759b9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditorengine/filters/FilterSharpness/Src/CFilterSharpness.cpp	Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,639 @@
+/*
+* 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 "CFilterSharpness.h"
+
+EXPORT_C TInt CFilterSharpness::Create()
+	{
+	CFilterSharpness* ptr = NULL;
+	TRAPD( error, ptr = NewL(); );
+	if( error != KErrNone )
+		{
+		ptr = NULL;
+		}
+	return (TInt)((MImageFilter*)ptr);
+	}
+
+
+
+CFilterSharpness* CFilterSharpness::NewL()
+	{
+	CFilterSharpness* self = new( ELeave )CFilterSharpness();
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+	}
+
+
+
+CFilterSharpness::~CFilterSharpness()
+	{
+	delete[] ipRCR;
+	delete[] ipRCG;
+	delete[] ipRCB;
+	delete[] ipCCR;
+	delete[] ipCCG;
+	delete[] ipCCB;
+    delete[] iDivLUT;
+	}
+
+
+
+CFilterSharpness::CFilterSharpness()
+	{
+
+	}
+
+
+
+void CFilterSharpness::ConstructL()
+	{
+	}
+
+
+
+TRect CFilterSharpness::Rect()
+	{
+	return iChild->Rect();
+	}
+
+TReal CFilterSharpness::Scale()
+	{
+	return iChild->Scale();
+	}
+
+TSize CFilterSharpness::ViewPortSize()
+{
+    return iChild->ViewPortSize();
+}
+
+
+TBlock * CFilterSharpness::GetBlockL ( const TRect & aRect )
+{
+
+    if (iN == 1)
+    {
+        return iChild->GetBlockL(aRect);
+    }
+
+    //  Read the block needed to create sharpened block aRect
+    TRect rect = aRect;
+    rect.iTl.iX -= iHN;
+    rect.iTl.iY -= iHN;
+    rect.iBr.iX += iHN;
+    rect.iBr.iY += iHN;
+    TBlock * pS = iChild->GetBlockL(rect);
+    if (!pS) return NULL;
+
+    //  Create resulting sharpened block
+    TBlock * pB = new (ELeave) TBlock (aRect);
+    TUint32 * pd = pB->iData;
+
+    TInt i = aRect.iTl.iY;      //  pixel index y
+    TInt j = aRect.iTl.iX;      //  pixel index x
+
+    TInt sumR = 0;
+    TInt sumG = 0;
+    TInt sumB = 0;
+    TInt rowsumR = 0;
+    TInt rowsumG = 0;         
+    TInt rowsumB = 0;
+
+    TInt irc = 0;               //  row cache index
+    TInt icc = 0;               //  column cache index
+
+
+    //  NW corner of the block => initialize row cache
+    for (TInt ii = -iHN; ii <= iHN; ++ii)
+    {
+
+        TInt y = i + ii;
+        if (y < pS->iRect.iTl.iY)
+        {
+            y = pS->iRect.iTl.iY;
+        }
+        else if (y >= pS->iRect.iBr.iY)
+        {
+            y = pS->iRect.iBr.iY - 1;
+        }
+        TInt offset = (y - pS->iRect.iTl.iY) * pS->iWidth - pS->iRect.iTl.iX;
+
+        for (TInt jj = -iHN; jj <= iHN; ++jj)
+        {
+        
+            TInt x = j + jj;
+            if (x < pS->iRect.iTl.iX)
+            {
+                x = pS->iRect.iTl.iX;
+            }
+            else if (x >= pS->iRect.iBr.iX)
+            {
+                x = pS->iRect.iBr.iX - 1;
+            }
+
+            TUint32 cc = *(pS->iData + offset + x);
+            rowsumB += cc & 0xFF;
+            ipRCB[irc] = (TUint8)(cc & 0xFF);    
+
+            cc >>= 8;
+            rowsumG += cc & 0xFF;
+            ipRCG[irc] = (TUint8)(cc & 0xFF);    
+            
+            cc >>= 8;
+            rowsumR += cc & 0xFF;
+            ipRCR[irc] = (TUint8)(cc & 0xFF);
+
+            irc++;
+            if (irc >= iN2) irc = 0;
+
+            
+        }
+    }
+
+	if ( iSharpen )
+	{
+        TUint32 c = *(pS->iData + (i - pS->iRect.iTl.iY) * pS->iWidth + (j - pS->iRect.iTl.iX));
+		
+		//	Get pixel from the previous filter
+		TInt bb = c & 0xFF;
+		bb += (bb - iDivLUT[rowsumB]);
+		if (bb < 0)
+		{ 
+			bb = 0;
+		}
+		else if (bb > 255)
+		{
+			bb = 255;
+		}
+
+		c >>= 8;
+		TInt gg = c & 0xFF;
+		gg += (gg - iDivLUT[rowsumG]);
+		if (gg < 0)
+		{ 
+			gg = 0;
+		}
+		else if (gg > 255)
+		{
+			gg = 255;
+		}
+
+		c >>= 8;
+		TInt  rr = c & 0xFF;
+		rr += (rr - iDivLUT[rowsumR]);
+		if (rr < 0)
+		{ 
+			rr = 0;
+		}
+		else if (rr > 255)
+		{
+			rr = 255;
+		}
+        *pd++ = (rr << 16) | (gg << 8) | bb;
+	}
+	else
+	{
+        *pd++ = ( (iDivLUT[rowsumR] << 16) |  (iDivLUT[rowsumG] << 8) | iDivLUT[rowsumB] );
+	}
+
+
+    //  Initialize column sum
+    sumB = rowsumB;
+    sumG = rowsumG;
+    sumR = rowsumR;
+
+    //  Update column cache
+    for (TInt iii = 0; iii < iN; ++iii)
+    {
+        for (TInt jjj = 0; jjj < iN; ++jjj)
+        {
+            ipCCR[iii * iN + jjj] = ipRCR[jjj * iN + iii];
+            ipCCG[iii * iN + jjj] = ipRCG[jjj * iN + iii];
+            ipCCB[iii * iN + jjj] = ipRCB[jjj * iN + iii];
+        }
+    }
+
+
+    //  Filter the rest of the first row
+    for ( j++ ; j < aRect.iBr.iX; ++j)
+    {
+
+        TInt x = j + iHN;
+        if (x < pS->iRect.iTl.iX)
+        {
+            x = pS->iRect.iTl.iX;
+        }
+        else if (x >= pS->iRect.iBr.iX)
+        {
+            x = pS->iRect.iBr.iX - 1;
+        }
+        TInt offset = x - pS->iRect.iTl.iX - pS->iRect.iTl.iY * pS->iWidth;
+
+        for (TInt ii = -iHN; ii <= iHN; ++ii)
+        {
+
+            TInt y = i + ii;
+            if (y < pS->iRect.iTl.iY)
+            {
+                y = pS->iRect.iTl.iY;
+            }
+            else if (y >= pS->iRect.iBr.iY)
+            {
+                y = pS->iRect.iBr.iY - 1;
+            }
+
+            TUint32 cc = *(pS->iData + y * pS->iWidth + offset);
+            sumB -= ipCCB[icc];
+            sumB += cc & 0xFF;
+            ipCCB[icc] = (TUint8)(cc & 0xFF);    
+
+            cc >>= 8;
+            sumG -= ipCCG[icc];
+            sumG += cc & 0xFF;
+            ipCCG[icc] = (TUint8)(cc & 0xFF);    
+            
+            cc >>= 8;
+            sumR -= ipCCR[icc];
+            sumR += cc & 0xFF;
+            ipCCR[icc] = (TUint8)(cc & 0xFF);    
+
+            icc++;
+            if (icc >= iN2) icc = 0;
+
+        }
+
+	    if ( iSharpen )
+	    {
+            TUint32 c = *(pS->iData + (i - pS->iRect.iTl.iY) * pS->iWidth + (j - pS->iRect.iTl.iX));
+		    
+		    //	Get pixel from the previous filter
+		    TInt bb = c & 0xFF;
+		    bb += (bb - iDivLUT[sumB]);
+		    if (bb < 0)
+		    { 
+			    bb = 0;
+		    }
+		    else if (bb > 255)
+		    {
+			    bb = 255;
+		    }
+
+		    c >>= 8;
+		    TInt gg = c & 0xFF;
+		    gg += (gg - iDivLUT[sumG]);
+		    if (gg < 0)
+		    { 
+			    gg = 0;
+		    }
+		    else if (gg > 255)
+		    {
+			    gg = 255;
+		    }
+
+		    c >>= 8;
+		    TInt  rr = c & 0xFF;
+		    rr += (rr - iDivLUT[sumR]);
+		    if (rr < 0)
+		    { 
+			    rr = 0;
+		    }
+		    else if (rr > 255)
+		    {
+			    rr = 255;
+		    }
+            *pd++ = (rr << 16) | (gg << 8) | bb;
+	    }
+	    else
+	    {
+            *pd++ = ( (iDivLUT[sumR] << 16) |  (iDivLUT[sumG] << 8) | iDivLUT[sumB] );
+	    }
+
+    }
+
+
+    //  Filter the rest of the block
+    for ( i++; i < aRect.iBr.iY; ++i)
+    {
+     
+        j = aRect.iTl.iX;
+        icc = 0;
+        
+        //  New row, add new row to row cache and remove old row, update column cache
+        TInt y = i + iHN;
+        if (y < pS->iRect.iTl.iY)
+        {
+            y = pS->iRect.iTl.iY;
+        }
+        else if (y >= pS->iRect.iBr.iY)
+        {
+            y = pS->iRect.iBr.iY - 1;
+        }
+        TInt offset = (y - pS->iRect.iTl.iY) * pS->iWidth - pS->iRect.iTl.iX;
+
+        for (TInt jj = -iHN; jj <= iHN; ++jj)
+        {
+
+            TInt x = j + jj;
+            if (x < pS->iRect.iTl.iX)
+            {
+                x = pS->iRect.iTl.iX;
+            }
+            else if (x >= pS->iRect.iBr.iX)
+            {
+                x = pS->iRect.iBr.iX - 1;
+            }
+
+            TUint32 cc = *(pS->iData + offset + x);
+            rowsumB -= ipRCB[irc];
+            rowsumB += cc & 0xFF;
+            ipRCB[irc] = (TUint8)(cc & 0xFF);    
+
+            cc >>= 8;
+            rowsumG -= ipRCG[irc];
+            rowsumG += cc & 0xFF;
+            ipRCG[irc] = (TUint8)(cc & 0xFF);    
+    
+            cc >>= 8;
+            rowsumR -= ipRCR[irc];
+            rowsumR += cc & 0xFF;
+            ipRCR[irc] = (TUint8)(cc & 0xFF);
+
+            irc++;
+            if (irc >= iN2) irc = 0;
+   
+        }
+
+	    if ( iSharpen )
+	    {
+            TUint32 c = *(pS->iData + (i - pS->iRect.iTl.iY) * pS->iWidth + (j - pS->iRect.iTl.iX));
+		    
+		    //	Get pixel from the previous filter
+		    TInt bb = c & 0xFF;
+		    bb += (bb - iDivLUT[rowsumB]);
+		    if (bb < 0)
+		    { 
+			    bb = 0;
+		    }
+		    else if (bb > 255)
+		    {
+			    bb = 255;
+		    }
+
+		    c >>= 8;
+		    TInt gg = c & 0xFF;
+		    gg += (gg - iDivLUT[rowsumG]);
+		    if (gg < 0)
+		    { 
+			    gg = 0;
+		    }
+		    else if (gg > 255)
+		    {
+			    gg = 255;
+		    }
+
+		    c >>= 8;
+		    TInt  rr = c & 0xFF;
+		    rr += (rr - iDivLUT[rowsumR]);
+		    if (rr < 0)
+		    { 
+			    rr = 0;
+		    }
+		    else if (rr > 255)
+		    {
+			    rr = 255;
+		    }
+            *pd++ = (rr << 16) | (gg << 8) | bb;
+	    }
+	    else
+	    {
+            *pd++ = ( (iDivLUT[rowsumR] << 16) |  (iDivLUT[rowsumG] << 8) | iDivLUT[rowsumB] );
+	    }
+
+        sumR = rowsumR;
+        sumG = rowsumG;         
+        sumB = rowsumB;
+
+        //  Update column cache
+        for (TInt iii = 0; iii < iN; ++iii)
+        {
+            for (TInt jjj = 0; jjj < iN; ++jjj)
+            {
+                ipCCR[iii * iN + jjj] = ipRCR[jjj * iN + iii];
+                ipCCG[iii * iN + jjj] = ipRCG[jjj * iN + iii];
+                ipCCB[iii * iN + jjj] = ipRCB[jjj * iN + iii];
+            }
+        }
+
+        //  Filter the rest of the row
+        for ( j++; j < aRect.iBr.iX; ++j)
+        {
+
+            TInt x = j + iHN;
+            if (x < pS->iRect.iTl.iX)
+            {
+                x = pS->iRect.iTl.iX;
+            }
+            else if (x >= pS->iRect.iBr.iX)
+            {
+                x = pS->iRect.iBr.iX - 1;
+            }
+            TInt offset = x - pS->iRect.iTl.iX - pS->iRect.iTl.iY * pS->iWidth;
+
+            for (TInt ii = -iHN; ii <= iHN; ++ii)
+            {
+
+                TInt y = i + ii;
+                if (y < pS->iRect.iTl.iY)
+                {
+                    y = pS->iRect.iTl.iY;
+                }
+                else if (y >= pS->iRect.iBr.iY)
+                {
+                    y = pS->iRect.iBr.iY - 1;
+                }
+
+                TUint32 cc = *(pS->iData + y * pS->iWidth + offset);
+                sumB -= ipCCB[icc];
+                sumB += cc & 0xFF;
+                ipCCB[icc] = (TUint8)(cc & 0xFF);    
+
+                cc >>= 8;
+                sumG -= ipCCG[icc];
+                sumG += cc & 0xFF;
+                ipCCG[icc] = (TUint8)(cc & 0xFF);    
+            
+                cc >>= 8;
+                sumR -= ipCCR[icc];
+                sumR += cc & 0xFF;
+                ipCCR[icc] = (TUint8)(cc & 0xFF);    
+
+                icc++;
+                if (icc >= iN2) icc = 0;
+
+            }
+            
+	        if ( iSharpen )
+	        {
+                TUint32 c = *(pS->iData + (i - pS->iRect.iTl.iY) * pS->iWidth + (j - pS->iRect.iTl.iX));
+		        
+		        //	Get pixel from the previous filter
+		        TInt bb = c & 0xFF;
+		        bb += (bb - iDivLUT[sumB]);
+		        if (bb < 0)
+		        { 
+			        bb = 0;
+		        }
+		        else if (bb > 255)
+		        {
+			        bb = 255;
+		        }
+
+		        c >>= 8;
+		        TInt gg = c & 0xFF;
+		        gg += (gg - iDivLUT[sumG]);
+		        if (gg < 0)
+		        { 
+			        gg = 0;
+		        }
+		        else if (gg > 255)
+		        {
+			        gg = 255;
+		        }
+
+		        c >>= 8;
+		        TInt  rr = c & 0xFF;
+		        rr += (rr - iDivLUT[sumR]);
+		        if (rr < 0)
+		        { 
+			        rr = 0;
+		        }
+		        else if (rr > 255)
+		        {
+			        rr = 255;
+		        }
+                *pd++ = (rr << 16) | (gg << 8) | bb;
+	        }
+	        else
+	        {
+                *pd++ = ( (iDivLUT[sumR] << 16) |  (iDivLUT[sumG] << 8) | iDivLUT[sumB] );
+	        }
+        }
+    }
+
+    delete pS;
+    pS = NULL;
+    return pB;
+}
+
+void CFilterSharpness::SetParent( MImageFilter* aParent )
+	{
+	iParent = aParent;
+	}
+
+
+void CFilterSharpness::SetChild( MImageFilter* aChild )
+	{
+	iChild = aChild;
+	}
+
+
+
+TInt CFilterSharpness::CmdL( const TDesC16 & aCmd )
+{
+	TLex lex (aCmd);
+
+    //  Get sharpness [-100,100]
+	while ( ! lex.Eos() )
+    {
+		TPtrC token = lex.NextToken();
+
+        if ( token.Compare( _L("sharpness") ) == 0)
+        {
+			lex.Inc();
+			lex.Val (iSharpness);
+		}
+    }
+	if (iSharpness < -100)
+	{
+		iSharpness = -100;
+
+	}
+	else if (iSharpness > 100)
+	{
+		iSharpness = 100;
+	}
+
+	if (iSharpness < 0)
+	{
+		iN = (-iSharpness / 10) + 1;
+		iSharpen = ETrue;
+	}
+	else
+	{
+		iN = (iSharpness / 10) + 1;
+		iSharpen = EFalse;
+	}
+	if ( iN % 2 == 0 )
+	{
+		iN++;
+	}
+	iN2 = iN * iN;
+	iHN = (iN >> 1);
+	
+    //  Create row caches for new filter size
+	delete[] ipRCR;
+	ipRCR = new (ELeave) TUint8 [iN2];
+	delete[] ipRCG;
+	ipRCG = new (ELeave) TUint8 [iN2];
+	delete[] ipRCB;
+	ipRCB = new (ELeave) TUint8 [iN2];
+	
+    //  Create column caches for new filter size
+	delete[] ipCCR;
+	ipCCR = new (ELeave) TUint8 [iN2];
+	delete[] ipCCG;
+	ipCCG = new (ELeave) TUint8 [iN2];
+	delete[] ipCCB;
+	ipCCB = new (ELeave) TUint8 [iN2];
+
+    //  Create and compute division LUT
+    delete[] iDivLUT;
+    TInt maxbins = iN2 * 255 + 1;
+    iDivLUT = new (ELeave) TUint8 [maxbins];
+    for (TInt i = 0; i < maxbins; ++i)
+    {
+        iDivLUT[i] = (TUint8)(i / iN2);
+    }
+
+
+    return 0;
+}
+	
+const char* CFilterSharpness::Type()
+{
+	return "sharpness";
+}
+
+#if !defined(EKA2)
+GLDEF_C TInt E32Dll( TDllReason )
+    {
+    return KErrNone;
+    }	
+#endif