imageeditorengine/filters/FilterRedEye/Src/CFilterRedEye.cpp
changeset 1 edfc90759b9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imageeditorengine/filters/FilterRedEye/Src/CFilterRedEye.cpp	Fri Jan 29 13:53:17 2010 +0200
@@ -0,0 +1,306 @@
+/*
+* 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 "CFilterRedEye.h"
+
+
+const TInt KHueRedLimitLow	= 15;
+const TInt KHueRedLimitHigh = 245;
+const TInt KSatLimitLow		= 80; 
+
+//=============================================================================
+EXPORT_C TInt CFilterRedEye::Create()
+	{
+	CFilterRedEye * ptr = NULL;
+	TRAPD( error, ptr = NewL(); );
+	if( error != KErrNone )
+		{
+		ptr = NULL;
+		}
+	return (TInt)((MImageFilter*)ptr);
+	}
+
+//=============================================================================
+CFilterRedEye* CFilterRedEye::NewL()
+	{
+	CFilterRedEye* self = new( ELeave )CFilterRedEye();
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	return self;
+	}
+
+//=============================================================================
+CFilterRedEye::~CFilterRedEye()
+	{
+	}
+
+
+//=============================================================================
+CFilterRedEye::CFilterRedEye()
+	{
+
+	}
+
+//=============================================================================
+void CFilterRedEye::ConstructL()
+	{
+
+	}
+
+//=============================================================================
+TRect CFilterRedEye::Rect()
+	{
+	return iChild->Rect();
+	}
+
+//=============================================================================
+TReal CFilterRedEye::Scale()
+	{
+	return iChild->Scale();
+	}
+
+//=============================================================================
+TSize CFilterRedEye::ViewPortSize()
+{
+    return iChild->ViewPortSize();
+}
+
+//=============================================================================
+TBlock * CFilterRedEye::GetBlockL ( const TRect & aRect )
+{
+    TBlock * pB = iChild->GetBlockL(aRect);
+    if (!pB) return NULL;
+    if ( iRedEyeRectSc.Intersects (aRect) )
+    {
+        TUint32 * pD = pB->iData;
+        TInt column = 0;
+        TInt rows = 0;
+        for (TInt i = 0; i < pB->iDataLength; ++i, ++pD)
+        {        
+		    TUint8 hue = Hue (*pD);
+		    TUint8 sat = Saturation (*pD);
+		    if ( ((hue < KHueRedLimitLow) || (hue > KHueRedLimitHigh)) && (sat > KSatLimitLow) )
+		    {
+				// Check if the pixel is inside the intersection of 
+				// the requested block and the red eye rect
+		        if (aRect.iTl.iX + column >= iRedEyeRectSc.iTl.iX &&
+		            aRect.iTl.iY + rows >= iRedEyeRectSc.iTl.iY &&
+                    aRect.iTl.iX + column < iRedEyeRectSc.iBr.iX &&
+                    aRect.iTl.iY + rows < iRedEyeRectSc.iBr.iY)
+		        {
+					// Check if the pixel is inside the cirle that fits 
+					// into the red eye rect (assuming it is square).
+					TInt r = static_cast<TInt> ( (TReal)(iRedEyeRectSc.iBr.iX - iRedEyeRectSc.iTl.iX) / 2 + 0.5);
+					TInt a = (iRedEyeRectSc.iTl.iX + r) - (aRect.iTl.iX + column);
+					TInt b = (iRedEyeRectSc.iTl.iY + r) - (aRect.iTl.iY + rows);
+					if ( (a*a + b*b) <= r*r )
+					{
+						TUint32 c = *pD;
+						TUint8 cb = (TUint8)(c & 0xFF);
+						c >>= 8;
+						TUint8 cg = (TUint8)(c & 0xFF);
+						c >>= 8;
+						TUint8 cr = (TUint8)(c & 0xFF);
+						TUint8 y = (TUint8)((306 * cr + 587 * cg + 117 * cb) >> 10);
+						*pD = (y | (y << 8) | (y << 16));
+					}
+		        }
+		    }
+
+		    ++column;
+		    if (column >= pB->iWidth)
+		    {
+		        column = 0;
+		        ++rows;
+		    }
+        }
+    }
+    return pB;
+}
+
+
+//=============================================================================
+void CFilterRedEye::SetParent( MImageFilter* aParent )
+	{
+	iParent = aParent;
+	}
+
+//=============================================================================
+void CFilterRedEye::SetChild( MImageFilter* aChild )
+	{
+	iChild = aChild;
+	}
+
+//=============================================================================
+TInt CFilterRedEye::CmdL( const TDesC16& aCmd )
+	{
+
+	TLex lex (aCmd);
+
+	while ( !lex.Eos() )
+	{
+		TPtrC token = lex.NextToken();
+		if( token.Compare( _L("ulc") ) == 0 )
+			{
+			TReal relscale = iChild->Scale();
+			TInt param = 0;
+			lex.Inc();
+			lex.Val( param );
+			iRedEyeRect.iTl.iX = (TInt)((param / relscale) + 0.5);
+			}
+		else if( token.Compare( _L("ulr") ) == 0 )
+			{
+			TReal relscale = iChild->Scale();
+			TInt param = 0;
+			lex.Inc();
+			lex.Val( param );
+			iRedEyeRect.iTl.iY = (TInt)((param / relscale) + 0.5);
+			}
+		else if( token.Compare( _L("lrc") ) == 0 )
+			{
+			TReal relscale = iChild->Scale();
+			TInt param = 0;
+			lex.Inc();
+			lex.Val( param );
+			iRedEyeRect.iBr.iX = (TInt)((param / relscale) + 0.5);
+			}
+		else if( token.Compare( _L("lrr") ) == 0 )
+			{
+			TReal relscale = iChild->Scale();
+			TInt param = 0;
+			lex.Inc();
+			lex.Val( param );
+			iRedEyeRect.iBr.iY = (TInt)((param / relscale) + 0.5);
+			}
+		}
+
+    TReal relscale = iChild->Scale();
+    iRedEyeRectSc.iTl.iX = (TInt)(iRedEyeRect.iTl.iX * relscale + 0.5);
+    iRedEyeRectSc.iTl.iY = (TInt)(iRedEyeRect.iTl.iY * relscale + 0.5);
+    iRedEyeRectSc.iBr.iX = (TInt)(iRedEyeRect.iBr.iX * relscale + 0.5);
+    iRedEyeRectSc.iBr.iY = (TInt)(iRedEyeRect.iBr.iY * relscale + 0.5);
+
+    return 0;
+
+	}
+
+//=============================================================================
+const char* CFilterRedEye::Type()
+	{
+	return "negate";
+	}
+	
+//=============================================================================
+TUint8 CFilterRedEye::Hue ( TUint32 aPixel ) const
+{
+
+	TUint8 g = (TUint8)(aPixel & 0xFF); 
+	aPixel >>= 8;
+	TUint8 b = (TUint8)(aPixel & 0xFF); 
+	aPixel >>= 8;
+	TUint8 r = (TUint8)(aPixel & 0xFF);
+
+	const TInt t1 = (1 << 10);
+	const TInt t3 = (3 << 10);
+	const TInt t5 = (5 << 10);
+	const TInt t6 = (6 << 10);
+	
+	TInt h = 0;
+	TInt v = ( r > g ) ? ( (r > b) ? (r) : (b) ) : ( (g > b) ? (g) : (b) );
+	TInt m = ( r < g ) ? ( (r < b) ? (r) : (b) ) : ( (g < b) ? (g) : (b) );
+
+	if (v != m) 
+	{
+
+		TInt vm = v - m;
+
+		if (r == v) 
+		{
+			TInt g2 = ((v - g) << 10) / vm;
+			TInt b2 = ((v - b) << 10) / vm;
+			h = (g == m) ? (t5 + b2) : (t1 - g2);
+		}
+
+		else if (g == v) 
+		{
+			TInt r2 = ((v - r) << 10) / vm;
+			TInt b2 = ((v - b) << 10) / vm;
+			h = (b == m) ? (t1 + r2) : (t3 - b2);
+		}
+
+		else 
+		{
+			TInt r2 = ((v - r) << 10) / vm;
+			TInt g2 = ((v - g) << 10) / vm;
+			h = (r == m) ? (t3 + g2) : (t5 - r2);
+		}
+
+		h *= 255;
+		h /= t6;
+	}
+
+	return (TUint8)h;
+}
+
+//=============================================================================
+TUint8 CFilterRedEye::Saturation ( TUint32 aPixel ) const
+{
+	TUint8 g = (TUint8)(aPixel & 0xFF); 
+	aPixel >>= 8;
+	TUint8 b = (TUint8)(aPixel & 0xFF); 
+	aPixel >>= 8;
+	TUint8 r = (TUint8)(aPixel & 0xFF);
+
+	TInt v = ( r > g ) ? ( (r > b) ? (r) : (b) ) : ( (g > b) ? (g) : (b) );
+	TInt m = ( r < g ) ? ( (r < b) ? (r) : (b) ) : ( (g < b) ? (g) : (b) );
+	TInt l = ((m + v) >> 1);
+	TInt s = 0;
+
+	if (l > 0) 
+	{
+		s = v - m;
+
+		if (s > 0) {
+
+			s *= 255;
+
+			if (l <= 127)
+			{
+				s /= (v + m);
+			}
+			else 
+			{
+				s /= (512 - v - m);
+			}
+		}
+	}
+	else {
+		s = 0;
+	}	
+	return (TUint8)s;
+}
+
+//=============================================================================
+#if !defined(EKA2)
+GLDEF_C TInt E32Dll( TDllReason )
+    {
+    return KErrNone;
+    }	
+#endif