|
1 /* |
|
2 * Copyright (c) 2010 Ixonos Plc. |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - Initial contribution |
|
11 * |
|
12 * Contributors: |
|
13 * Ixonos Plc |
|
14 * |
|
15 * Description: |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include "CFilterRedEye.h" |
|
21 |
|
22 |
|
23 const TInt KHueRedLimitLow = 15; |
|
24 const TInt KHueRedLimitHigh = 245; |
|
25 const TInt KSatLimitLow = 80; |
|
26 |
|
27 //============================================================================= |
|
28 EXPORT_C TInt CFilterRedEye::Create() |
|
29 { |
|
30 CFilterRedEye * ptr = NULL; |
|
31 TRAPD( error, ptr = NewL(); ); |
|
32 if( error != KErrNone ) |
|
33 { |
|
34 ptr = NULL; |
|
35 } |
|
36 return (TInt)((MImageFilter*)ptr); |
|
37 } |
|
38 |
|
39 //============================================================================= |
|
40 CFilterRedEye* CFilterRedEye::NewL() |
|
41 { |
|
42 CFilterRedEye* self = new( ELeave )CFilterRedEye(); |
|
43 CleanupStack::PushL( self ); |
|
44 self->ConstructL(); |
|
45 CleanupStack::Pop( self ); |
|
46 return self; |
|
47 } |
|
48 |
|
49 //============================================================================= |
|
50 CFilterRedEye::~CFilterRedEye() |
|
51 { |
|
52 } |
|
53 |
|
54 |
|
55 //============================================================================= |
|
56 CFilterRedEye::CFilterRedEye() |
|
57 { |
|
58 |
|
59 } |
|
60 |
|
61 //============================================================================= |
|
62 void CFilterRedEye::ConstructL() |
|
63 { |
|
64 |
|
65 } |
|
66 |
|
67 //============================================================================= |
|
68 TRect CFilterRedEye::Rect() |
|
69 { |
|
70 return iChild->Rect(); |
|
71 } |
|
72 |
|
73 //============================================================================= |
|
74 TReal CFilterRedEye::Scale() |
|
75 { |
|
76 return iChild->Scale(); |
|
77 } |
|
78 |
|
79 //============================================================================= |
|
80 TSize CFilterRedEye::ViewPortSize() |
|
81 { |
|
82 return iChild->ViewPortSize(); |
|
83 } |
|
84 |
|
85 //============================================================================= |
|
86 TBlock * CFilterRedEye::GetBlockL ( const TRect & aRect ) |
|
87 { |
|
88 TBlock * pB = iChild->GetBlockL(aRect); |
|
89 if (!pB) return NULL; |
|
90 if ( iRedEyeRectSc.Intersects (aRect) ) |
|
91 { |
|
92 TUint32 * pD = pB->iData; |
|
93 TInt column = 0; |
|
94 TInt rows = 0; |
|
95 for (TInt i = 0; i < pB->iDataLength; ++i, ++pD) |
|
96 { |
|
97 TUint8 hue = Hue (*pD); |
|
98 TUint8 sat = Saturation (*pD); |
|
99 if ( ((hue < KHueRedLimitLow) || (hue > KHueRedLimitHigh)) && (sat > KSatLimitLow) ) |
|
100 { |
|
101 // Check if the pixel is inside the intersection of |
|
102 // the requested block and the red eye rect |
|
103 if (aRect.iTl.iX + column >= iRedEyeRectSc.iTl.iX && |
|
104 aRect.iTl.iY + rows >= iRedEyeRectSc.iTl.iY && |
|
105 aRect.iTl.iX + column < iRedEyeRectSc.iBr.iX && |
|
106 aRect.iTl.iY + rows < iRedEyeRectSc.iBr.iY) |
|
107 { |
|
108 // Check if the pixel is inside the cirle that fits |
|
109 // into the red eye rect (assuming it is square). |
|
110 TInt r = static_cast<TInt> ( (TReal)(iRedEyeRectSc.iBr.iX - iRedEyeRectSc.iTl.iX) / 2 + 0.5); |
|
111 TInt a = (iRedEyeRectSc.iTl.iX + r) - (aRect.iTl.iX + column); |
|
112 TInt b = (iRedEyeRectSc.iTl.iY + r) - (aRect.iTl.iY + rows); |
|
113 if ( (a*a + b*b) <= r*r ) |
|
114 { |
|
115 TUint32 c = *pD; |
|
116 TUint8 cb = (TUint8)(c & 0xFF); |
|
117 c >>= 8; |
|
118 TUint8 cg = (TUint8)(c & 0xFF); |
|
119 c >>= 8; |
|
120 TUint8 cr = (TUint8)(c & 0xFF); |
|
121 TUint8 y = (TUint8)((306 * cr + 587 * cg + 117 * cb) >> 10); |
|
122 *pD = (y | (y << 8) | (y << 16)); |
|
123 } |
|
124 } |
|
125 } |
|
126 |
|
127 ++column; |
|
128 if (column >= pB->iWidth) |
|
129 { |
|
130 column = 0; |
|
131 ++rows; |
|
132 } |
|
133 } |
|
134 } |
|
135 return pB; |
|
136 } |
|
137 |
|
138 |
|
139 //============================================================================= |
|
140 void CFilterRedEye::SetParent( MImageFilter* aParent ) |
|
141 { |
|
142 iParent = aParent; |
|
143 } |
|
144 |
|
145 //============================================================================= |
|
146 void CFilterRedEye::SetChild( MImageFilter* aChild ) |
|
147 { |
|
148 iChild = aChild; |
|
149 } |
|
150 |
|
151 //============================================================================= |
|
152 TInt CFilterRedEye::CmdL( const TDesC16& aCmd ) |
|
153 { |
|
154 |
|
155 TLex lex (aCmd); |
|
156 |
|
157 while ( !lex.Eos() ) |
|
158 { |
|
159 TPtrC token = lex.NextToken(); |
|
160 if( token.Compare( _L("ulc") ) == 0 ) |
|
161 { |
|
162 TReal relscale = iChild->Scale(); |
|
163 TInt param = 0; |
|
164 lex.Inc(); |
|
165 lex.Val( param ); |
|
166 iRedEyeRect.iTl.iX = (TInt)((param / relscale) + 0.5); |
|
167 } |
|
168 else if( token.Compare( _L("ulr") ) == 0 ) |
|
169 { |
|
170 TReal relscale = iChild->Scale(); |
|
171 TInt param = 0; |
|
172 lex.Inc(); |
|
173 lex.Val( param ); |
|
174 iRedEyeRect.iTl.iY = (TInt)((param / relscale) + 0.5); |
|
175 } |
|
176 else if( token.Compare( _L("lrc") ) == 0 ) |
|
177 { |
|
178 TReal relscale = iChild->Scale(); |
|
179 TInt param = 0; |
|
180 lex.Inc(); |
|
181 lex.Val( param ); |
|
182 iRedEyeRect.iBr.iX = (TInt)((param / relscale) + 0.5); |
|
183 } |
|
184 else if( token.Compare( _L("lrr") ) == 0 ) |
|
185 { |
|
186 TReal relscale = iChild->Scale(); |
|
187 TInt param = 0; |
|
188 lex.Inc(); |
|
189 lex.Val( param ); |
|
190 iRedEyeRect.iBr.iY = (TInt)((param / relscale) + 0.5); |
|
191 } |
|
192 } |
|
193 |
|
194 TReal relscale = iChild->Scale(); |
|
195 iRedEyeRectSc.iTl.iX = (TInt)(iRedEyeRect.iTl.iX * relscale + 0.5); |
|
196 iRedEyeRectSc.iTl.iY = (TInt)(iRedEyeRect.iTl.iY * relscale + 0.5); |
|
197 iRedEyeRectSc.iBr.iX = (TInt)(iRedEyeRect.iBr.iX * relscale + 0.5); |
|
198 iRedEyeRectSc.iBr.iY = (TInt)(iRedEyeRect.iBr.iY * relscale + 0.5); |
|
199 |
|
200 return 0; |
|
201 |
|
202 } |
|
203 |
|
204 //============================================================================= |
|
205 const char* CFilterRedEye::Type() |
|
206 { |
|
207 return "negate"; |
|
208 } |
|
209 |
|
210 //============================================================================= |
|
211 TUint8 CFilterRedEye::Hue ( TUint32 aPixel ) const |
|
212 { |
|
213 |
|
214 TUint8 g = (TUint8)(aPixel & 0xFF); |
|
215 aPixel >>= 8; |
|
216 TUint8 b = (TUint8)(aPixel & 0xFF); |
|
217 aPixel >>= 8; |
|
218 TUint8 r = (TUint8)(aPixel & 0xFF); |
|
219 |
|
220 const TInt t1 = (1 << 10); |
|
221 const TInt t3 = (3 << 10); |
|
222 const TInt t5 = (5 << 10); |
|
223 const TInt t6 = (6 << 10); |
|
224 |
|
225 TInt h = 0; |
|
226 TInt v = ( r > g ) ? ( (r > b) ? (r) : (b) ) : ( (g > b) ? (g) : (b) ); |
|
227 TInt m = ( r < g ) ? ( (r < b) ? (r) : (b) ) : ( (g < b) ? (g) : (b) ); |
|
228 |
|
229 if (v != m) |
|
230 { |
|
231 |
|
232 TInt vm = v - m; |
|
233 |
|
234 if (r == v) |
|
235 { |
|
236 TInt g2 = ((v - g) << 10) / vm; |
|
237 TInt b2 = ((v - b) << 10) / vm; |
|
238 h = (g == m) ? (t5 + b2) : (t1 - g2); |
|
239 } |
|
240 |
|
241 else if (g == v) |
|
242 { |
|
243 TInt r2 = ((v - r) << 10) / vm; |
|
244 TInt b2 = ((v - b) << 10) / vm; |
|
245 h = (b == m) ? (t1 + r2) : (t3 - b2); |
|
246 } |
|
247 |
|
248 else |
|
249 { |
|
250 TInt r2 = ((v - r) << 10) / vm; |
|
251 TInt g2 = ((v - g) << 10) / vm; |
|
252 h = (r == m) ? (t3 + g2) : (t5 - r2); |
|
253 } |
|
254 |
|
255 h *= 255; |
|
256 h /= t6; |
|
257 } |
|
258 |
|
259 return (TUint8)h; |
|
260 } |
|
261 |
|
262 //============================================================================= |
|
263 TUint8 CFilterRedEye::Saturation ( TUint32 aPixel ) const |
|
264 { |
|
265 TUint8 g = (TUint8)(aPixel & 0xFF); |
|
266 aPixel >>= 8; |
|
267 TUint8 b = (TUint8)(aPixel & 0xFF); |
|
268 aPixel >>= 8; |
|
269 TUint8 r = (TUint8)(aPixel & 0xFF); |
|
270 |
|
271 TInt v = ( r > g ) ? ( (r > b) ? (r) : (b) ) : ( (g > b) ? (g) : (b) ); |
|
272 TInt m = ( r < g ) ? ( (r < b) ? (r) : (b) ) : ( (g < b) ? (g) : (b) ); |
|
273 TInt l = ((m + v) >> 1); |
|
274 TInt s = 0; |
|
275 |
|
276 if (l > 0) |
|
277 { |
|
278 s = v - m; |
|
279 |
|
280 if (s > 0) { |
|
281 |
|
282 s *= 255; |
|
283 |
|
284 if (l <= 127) |
|
285 { |
|
286 s /= (v + m); |
|
287 } |
|
288 else |
|
289 { |
|
290 s /= (512 - v - m); |
|
291 } |
|
292 } |
|
293 } |
|
294 else { |
|
295 s = 0; |
|
296 } |
|
297 return (TUint8)s; |
|
298 } |
|
299 |
|
300 //============================================================================= |
|
301 #if !defined(EKA2) |
|
302 GLDEF_C TInt E32Dll( TDllReason ) |
|
303 { |
|
304 return KErrNone; |
|
305 } |
|
306 #endif |