|
1 /* |
|
2 * Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * |
|
14 * Description: Provides convolution operations on images. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 #include "AknsRlEffectPluginConvolution.h" |
|
21 #include "AknsRlEffectUtil.h" |
|
22 #include "fx_asm_versions.h" |
|
23 |
|
24 // CONSTANTS |
|
25 |
|
26 // Fixed convolution kernels |
|
27 const TInt KKernelEdgeDetect[9] = { -1, -1, -1, |
|
28 -1, 8, -1, |
|
29 -1, -1, -1 }; |
|
30 |
|
31 const TInt KKernelBlur[9] = { 1, 2, 1, |
|
32 2, 2, 2, |
|
33 1, 2, 1 }; |
|
34 |
|
35 const TInt KKernelBlurGauss[9] = { 0, 1, 0, |
|
36 1, 4, 1, |
|
37 0, 1, 0 }; |
|
38 |
|
39 const TInt KKernelEmbossSoft[9] = { -1, 0, 0, |
|
40 0, 0, 0, |
|
41 0, 0, 1 }; |
|
42 |
|
43 const TInt KKernelEmbossHard[9] = { -1, -1, 0, |
|
44 -1, 0, 1, |
|
45 0, 1, 1 }; |
|
46 |
|
47 const TInt KKernelEnhanceDetail[9] = { 0, -1, 0, |
|
48 -1, 9, -1, |
|
49 0, -1, 0 }; |
|
50 |
|
51 const TInt KKernelEnhanceFocus[9] = { -1, 0, -1, |
|
52 0, 7, 0, |
|
53 -1, 0, -1 }; |
|
54 |
|
55 const TInt KKernelSoften[9] = { 1, 1, 1, |
|
56 1, 1, 1, |
|
57 1, 1, 1 }; |
|
58 |
|
59 const TInt KKernelSharpen[9] = { 0, -1, 0, |
|
60 -1, 5, -1, |
|
61 0, -1, 0 }; |
|
62 |
|
63 const TInt KKernelSharpenMore[9] = {-1, -1, -1, |
|
64 -1, 9, -1, |
|
65 -1, -1, -1 }; |
|
66 |
|
67 /*lint -save -e834 */ // Let's get real...not confusing |
|
68 |
|
69 // ==================== TEMPLATE IMPL. OF CONVOLUTION ========================== |
|
70 /** |
|
71 * Template implementation of Convolution. Type defines the used data type for |
|
72 * iterating over the bitmap data. X, R, G and B define the used pixel color bit |
|
73 * layout. |
|
74 */ |
|
75 template<class Type,TInt X, TInt R, TInt G, TInt B> |
|
76 class AknsRlEffectConvolution |
|
77 { |
|
78 public: |
|
79 //------------------------------------------------------------------------ |
|
80 /** |
|
81 * Convolutes a bitmap with generic 3x3 convolution kernel. |
|
82 */ |
|
83 static void Kernel( const CFbsBitmap& aTarget, |
|
84 const CFbsBitmap& aSource, |
|
85 const TInt aKernel[9], |
|
86 const TInt aBlendFactor, |
|
87 const TInt aBias ) |
|
88 { |
|
89 TInt width = aTarget.SizeInPixels().iWidth; |
|
90 TInt height = aTarget.SizeInPixels().iHeight; |
|
91 // ScanLineLength returns bytes, but width must match the Type |
|
92 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())) / sizeof(Type); |
|
93 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())) / sizeof(Type); |
|
94 |
|
95 TInt kernelSum = aKernel[0] + aKernel[1] + aKernel[2] + |
|
96 aKernel[3] + aKernel[4] + aKernel[5] + |
|
97 aKernel[6] + aKernel[7] + aKernel[8]; |
|
98 |
|
99 if( 0 == kernelSum ) |
|
100 kernelSum = 1; |
|
101 |
|
102 TInt r, g, b; |
|
103 TInt x, y; // Loop counters |
|
104 |
|
105 // Pitch is the number of pixels to skip before next scanline start |
|
106 TInt pitchTarget = scanWtarget - width; |
|
107 TInt pitchSource = scanWsource - width; |
|
108 |
|
109 // Prepare the data addresses |
|
110 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
111 Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() ); |
|
112 Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() ); |
|
113 |
|
114 dataS = dataS + scanWsource + 1; |
|
115 |
|
116 // Do the actual convolution |
|
117 for( y = 0; y < height; y++ ) |
|
118 { |
|
119 for( x = 0; x < width; x++ ) |
|
120 { |
|
121 r = aBias + (AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource - 1)) * aKernel[0] + |
|
122 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource )) * aKernel[1] + |
|
123 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource + 1)) * aKernel[2] + |
|
124 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - 1 )) * aKernel[3] + |
|
125 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS )) * aKernel[4] + |
|
126 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + 1 )) * aKernel[5] + |
|
127 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource - 1)) * aKernel[6] + |
|
128 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource )) * aKernel[7] + |
|
129 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource + 1)) * aKernel[8]) / kernelSum; |
|
130 |
|
131 g = aBias + (AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource - 1)) * aKernel[0] + |
|
132 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource )) * aKernel[1] + |
|
133 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource + 1)) * aKernel[2] + |
|
134 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - 1 )) * aKernel[3] + |
|
135 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS )) * aKernel[4] + |
|
136 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + 1 )) * aKernel[5] + |
|
137 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource - 1)) * aKernel[6] + |
|
138 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource )) * aKernel[7] + |
|
139 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource + 1)) * aKernel[8]) / kernelSum; |
|
140 |
|
141 |
|
142 b = aBias + (AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource - 1)) * aKernel[0] + |
|
143 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource )) * aKernel[1] + |
|
144 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource + 1)) * aKernel[2] + |
|
145 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - 1 )) * aKernel[3] + |
|
146 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS )) * aKernel[4] + |
|
147 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + 1 )) * aKernel[5] + |
|
148 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource - 1)) * aKernel[6] + |
|
149 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource )) * aKernel[7] + |
|
150 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource + 1)) * aKernel[8]) / kernelSum; |
|
151 |
|
152 |
|
153 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
154 // is supported -> negative values are shifted correctly |
|
155 r = ( r * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::R8(*dataS) ) >> 8; |
|
156 g = ( g * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::G8(*dataS) ) >> 8; |
|
157 b = ( b * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::B8(*dataS) ) >> 8; |
|
158 |
|
159 if( r < 0 ) r = 0; |
|
160 else if( r > 255 ) r = 255; |
|
161 |
|
162 if( g < 0 ) g = 0; |
|
163 else if( g > 255 ) g = 255; |
|
164 |
|
165 if( b < 0 ) b = 0; |
|
166 else if( b > 255 ) b = 255; |
|
167 |
|
168 AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(r), TUint8(g), TUint8(b) ); |
|
169 |
|
170 dataT++; |
|
171 dataS++; |
|
172 } |
|
173 |
|
174 dataT = dataT + pitchTarget; |
|
175 dataS = dataS + pitchSource; |
|
176 } |
|
177 |
|
178 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
179 } |
|
180 //------------------------------------------------------------------------ |
|
181 /** |
|
182 * "Convolutes" a bitmap with adjustable gaussian blur kernel. |
|
183 * Kernel size from 3*3 to 33*33 (odd sizes). |
|
184 */ |
|
185 static void AdjustableGaussian( const CFbsBitmap& aTarget, |
|
186 const CFbsBitmap& aSource, |
|
187 TUint16* aColumnBuffer, |
|
188 const TInt aKernelsize ) |
|
189 { |
|
190 TInt width = aTarget.SizeInPixels().iWidth; |
|
191 TInt height = aTarget.SizeInPixels().iHeight; |
|
192 // ScanLineLength returns bytes, but width must match the Type |
|
193 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())) / sizeof(Type); |
|
194 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())) / sizeof(Type); |
|
195 |
|
196 |
|
197 TUint16 r, g, b; |
|
198 r=0; |
|
199 g=0; |
|
200 b=0; |
|
201 TInt x, y, i; // Loop counters |
|
202 TInt bufIndx, bufIndxTarget; |
|
203 |
|
204 // Pitch is the number of pixels to skip before next scanline start |
|
205 TInt pitchTarget = scanWtarget - width; |
|
206 TInt pitchSource = scanWsource - width; |
|
207 |
|
208 // Prepare the data addresses |
|
209 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
210 Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() ); |
|
211 Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() ); |
|
212 Type* dataR = dataT; // for recursive iterations, both source and target are the same |
|
213 dataS = dataS + scanWsource + 1; // state machine takes pixel (1,1) and output goes to pixel (0,0) |
|
214 |
|
215 TUint16 tmp1; |
|
216 TUint16 tmp2; |
|
217 |
|
218 // row buffer variables for red, green and blue components |
|
219 TUint16 SR0r; |
|
220 TUint16 SR1r; |
|
221 TUint16 SR0g; |
|
222 TUint16 SR1g; |
|
223 TUint16 SR0b; |
|
224 TUint16 SR1b; |
|
225 |
|
226 TInt col0_rIndex; // index for row 0 columns in aColumnBuffer for red component |
|
227 TInt col1_rIndex; // index for row 1 columns in aColumnBuffer for red component |
|
228 TInt col0_gIndex; // index for row 0 columns in aColumnBuffer for green component |
|
229 TInt col1_gIndex; // index for row 1 columns in aColumnBuffer for green component |
|
230 TInt col0_bIndex; // index for row 0 columns in aColumnBuffer for blue component |
|
231 TInt col1_bIndex; // index for row 1 columns in aColumnBuffer for blue component |
|
232 |
|
233 TBool renderWithBuffers = ETrue; |
|
234 if ( aKernelsize < 7 ) // don't try to use temp buffers with small kernel |
|
235 renderWithBuffers = EFalse; |
|
236 |
|
237 TUint16* redBuffer; |
|
238 TUint16* greenBuffer; |
|
239 TUint16* blueBuffer; |
|
240 |
|
241 // to disable warnings |
|
242 redBuffer = NULL; |
|
243 greenBuffer = NULL; |
|
244 blueBuffer = NULL; |
|
245 |
|
246 if( renderWithBuffers ) |
|
247 { |
|
248 // OOM returns NULL |
|
249 redBuffer = new TUint16[(width+1)*(height+1)]; |
|
250 greenBuffer = new TUint16[(width+1)*(height+1)]; |
|
251 blueBuffer = new TUint16[(width+1)*(height+1)]; |
|
252 |
|
253 // All buffers are required for rendering |
|
254 if( !redBuffer || !greenBuffer || !blueBuffer ) |
|
255 { |
|
256 delete [] redBuffer; |
|
257 redBuffer = NULL; |
|
258 delete [] greenBuffer; |
|
259 greenBuffer = NULL; |
|
260 delete [] blueBuffer; |
|
261 blueBuffer = NULL; |
|
262 |
|
263 renderWithBuffers = EFalse; |
|
264 } |
|
265 } |
|
266 |
|
267 if( renderWithBuffers ) |
|
268 { |
|
269 i = width + 2; // start writing to pixel (1,1) |
|
270 for ( y = 0; y < (height - 1) ; y++ ) |
|
271 { |
|
272 for ( x = 0; x < (width - 1) ; x++ ) |
|
273 { |
|
274 redBuffer[i] = (TUint16)AknsRlRgb<Type,X,R,G,B>::R8(*dataS); |
|
275 greenBuffer[i] = (TUint16)AknsRlRgb<Type,X,R,G,B>::G8(*dataS); |
|
276 blueBuffer[i] = (TUint16)AknsRlRgb<Type,X,R,G,B>::B8(*dataS); |
|
277 i++; |
|
278 dataS++; |
|
279 } |
|
280 redBuffer[i] = redBuffer[i-1]; |
|
281 greenBuffer[i] = greenBuffer[i-1]; |
|
282 blueBuffer[i] = blueBuffer[i-1]; |
|
283 i+=2; // start from second pixel |
|
284 dataS = dataS + pitchSource + 1; // start from second pixel |
|
285 } |
|
286 |
|
287 for ( x = 0; x < width ; x++ ) // copy bottom row |
|
288 { |
|
289 redBuffer[i] = redBuffer[i-(width+1)]; |
|
290 greenBuffer[i] = greenBuffer[i-(width+1)]; |
|
291 blueBuffer[i] = blueBuffer[i-(width+1)]; |
|
292 i++; |
|
293 } |
|
294 |
|
295 redBuffer[1] = redBuffer[width+2]; // initialize these for row registers |
|
296 greenBuffer[1] = greenBuffer[width+2]; |
|
297 blueBuffer[1] = blueBuffer[width+2]; |
|
298 |
|
299 for ( i = 0; i < (aKernelsize - 1) >> 1 ; i++ ) // do (N-1) / 2 times |
|
300 { |
|
301 bufIndx = width+2; |
|
302 bufIndxTarget = 0; |
|
303 |
|
304 for( y = 0; y < height; y++ ) |
|
305 { |
|
306 SR0r = redBuffer[bufIndxTarget+1]; // initialize row buffer variables |
|
307 SR1r = redBuffer[bufIndxTarget+1]; |
|
308 SR0g = greenBuffer[bufIndxTarget+1]; |
|
309 SR1g = greenBuffer[bufIndxTarget+1]; |
|
310 SR0b = blueBuffer[bufIndxTarget+1]; |
|
311 SR1b = blueBuffer[bufIndxTarget+1]; |
|
312 col0_rIndex = 0; // initialize indexes for column buffers |
|
313 col1_rIndex = width; |
|
314 col0_gIndex = col1_rIndex + width; |
|
315 col1_gIndex = col0_gIndex + width; |
|
316 col0_bIndex = col1_gIndex + width; |
|
317 col1_bIndex = col0_bIndex + width; |
|
318 for( x = 0; x < width; x++ ) |
|
319 { |
|
320 // red |
|
321 tmp1 = redBuffer[bufIndx]; |
|
322 tmp2 = (TUint16)(SR0r + tmp1); |
|
323 SR0r = tmp1; |
|
324 tmp1 = (TUint16)(SR1r + tmp2); |
|
325 SR1r = tmp2; |
|
326 |
|
327 tmp2 = (TUint16)(aColumnBuffer[col0_rIndex] + tmp1); |
|
328 aColumnBuffer[col0_rIndex++] = tmp1; |
|
329 redBuffer[bufIndxTarget] = (TUint16)((8 + aColumnBuffer[col1_rIndex] + tmp2) >> 4); |
|
330 aColumnBuffer[col1_rIndex++] = tmp2; |
|
331 |
|
332 // green |
|
333 tmp1 = greenBuffer[bufIndx]; |
|
334 tmp2 = (TUint16)(SR0g + tmp1); |
|
335 SR0g = tmp1; |
|
336 tmp1 = (TUint16)(SR1g + tmp2); |
|
337 SR1g = tmp2; |
|
338 |
|
339 tmp2 = (TUint16)(aColumnBuffer[col0_gIndex] + tmp1); |
|
340 aColumnBuffer[col0_gIndex++] = tmp1; |
|
341 greenBuffer[bufIndxTarget] = (TUint16)((8 + aColumnBuffer[col1_gIndex] + tmp2) >> 4); |
|
342 aColumnBuffer[col1_gIndex++] = tmp2; |
|
343 |
|
344 // blue |
|
345 tmp1 = blueBuffer[bufIndx++]; |
|
346 tmp2 = (TUint16)(SR0b + tmp1); |
|
347 SR0b = tmp1; |
|
348 tmp1 = (TUint16)(SR1b + tmp2); |
|
349 SR1b = tmp2; |
|
350 |
|
351 tmp2 = (TUint16)(aColumnBuffer[col0_bIndex] + tmp1); |
|
352 aColumnBuffer[col0_bIndex++] = tmp1; |
|
353 b = (TUint16)((8 + aColumnBuffer[col1_bIndex] + tmp2) >> 4); |
|
354 blueBuffer[bufIndxTarget++] = (TUint16)b; |
|
355 aColumnBuffer[col1_bIndex++] = tmp2; |
|
356 } |
|
357 bufIndx++; |
|
358 bufIndxTarget++; |
|
359 } |
|
360 } |
|
361 |
|
362 // now write target from buffers |
|
363 i = 0; |
|
364 for ( y = 0; y < height ; y++ ) |
|
365 { |
|
366 for ( x = 0; x < width ; x++ ) |
|
367 { |
|
368 AknsRlRgb<Type,X,R,G,B>::SetRgb8LessG( dataT, |
|
369 redBuffer[i], |
|
370 greenBuffer[i], |
|
371 blueBuffer[i++] ); |
|
372 dataT++; |
|
373 } |
|
374 dataT = dataT + pitchTarget; |
|
375 i++; |
|
376 } |
|
377 |
|
378 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
379 delete [] redBuffer; |
|
380 delete [] greenBuffer; |
|
381 delete [] blueBuffer; |
|
382 return; |
|
383 } |
|
384 else |
|
385 { |
|
386 // Do the actual convolution |
|
387 for ( i = 0; i < (aKernelsize - 1) >> 1 ; i++ ) // do (N-1) / 2 times |
|
388 { |
|
389 |
|
390 for( y = 0; y < (height - 1); y++ ) |
|
391 { |
|
392 SR0r = 0; // initialize row buffer variables |
|
393 SR1r = 0; |
|
394 SR0g = 0; |
|
395 SR1g = 0; |
|
396 SR0b = 0; |
|
397 SR1b = 0; |
|
398 col0_rIndex = 0; // initialize indexes for column buffers |
|
399 col1_rIndex = width; |
|
400 col0_gIndex = col1_rIndex + width; |
|
401 col1_gIndex = col0_gIndex + width; |
|
402 col0_bIndex = col1_gIndex + width; |
|
403 col1_bIndex = col0_bIndex + width; |
|
404 for( x = 0; x < (width - 1); x++ ) |
|
405 { |
|
406 // red |
|
407 tmp1 = (TUint16)AknsRlRgb<Type,X,R,G,B>::R8(*dataS); |
|
408 tmp2 = (TUint16)(SR0r + tmp1); |
|
409 SR0r = tmp1; |
|
410 tmp1 = (TUint16)(SR1r + tmp2); |
|
411 SR1r = tmp2; |
|
412 |
|
413 tmp2 = (TUint16)(aColumnBuffer[col0_rIndex] + tmp1); |
|
414 aColumnBuffer[col0_rIndex++] = tmp1; |
|
415 r = (TUint16)((8 + aColumnBuffer[col1_rIndex] + tmp2) >> 4); |
|
416 aColumnBuffer[col1_rIndex++] = tmp2; |
|
417 |
|
418 // green |
|
419 tmp1 = (TUint16)AknsRlRgb<Type,X,R,G,B>::G8(*dataS); |
|
420 tmp2 = (TUint16)(SR0g + tmp1); |
|
421 SR0g = tmp1; |
|
422 tmp1 = (TUint16)(SR1g + tmp2); |
|
423 SR1g = tmp2; |
|
424 |
|
425 tmp2 = (TUint16)(aColumnBuffer[col0_gIndex] + tmp1); |
|
426 aColumnBuffer[col0_gIndex++] = tmp1; |
|
427 g = (TUint16)((8 + aColumnBuffer[col1_gIndex] + tmp2) >> 4); |
|
428 aColumnBuffer[col1_gIndex++] = tmp2; |
|
429 |
|
430 // blue |
|
431 tmp1 = (TUint16)AknsRlRgb<Type,X,R,G,B>::B8(*dataS); |
|
432 tmp2 = (TUint16)(SR0b + tmp1); |
|
433 SR0b = tmp1; |
|
434 tmp1 = (TUint16)(SR1b + tmp2); |
|
435 SR1b = tmp2; |
|
436 |
|
437 tmp2 = (TUint16)(aColumnBuffer[col0_bIndex] + tmp1); |
|
438 aColumnBuffer[col0_bIndex++] = tmp1; |
|
439 b = (TUint16)((8 + aColumnBuffer[col1_bIndex] + tmp2) >> 4); |
|
440 aColumnBuffer[col1_bIndex++] = tmp2; |
|
441 |
|
442 |
|
443 if( r > 255 ) r = 255; |
|
444 if( g > 255 ) g = 255; |
|
445 if( b > 255 ) b = 255; |
|
446 |
|
447 AknsRlRgb<Type,X,R,G,B>::SetRgb8LessG( dataT, r, g, b ); |
|
448 |
|
449 dataT++; |
|
450 dataS++; |
|
451 } |
|
452 |
|
453 dataT = dataT + pitchTarget + 1; |
|
454 dataS = dataS + pitchSource + 1; |
|
455 } |
|
456 dataT = dataR; // for more than 1 iterations, use target bitmap for both |
|
457 dataS = dataR+scanWtarget+1; // target and source |
|
458 } |
|
459 |
|
460 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
461 } |
|
462 } |
|
463 |
|
464 //------------------------------------------------------------------------ |
|
465 /** |
|
466 * Convolutes a bitmap by calculating the mean value of a 3x3 pixel |
|
467 * neighborhood as the resulting pixel value. |
|
468 */ |
|
469 static void Mean( const CFbsBitmap& aTarget, |
|
470 const CFbsBitmap& aSource, |
|
471 TInt aBlendFactor ) |
|
472 { |
|
473 TInt width = aTarget.SizeInPixels().iWidth; |
|
474 TInt height = aTarget.SizeInPixels().iHeight; |
|
475 // ScanLineLength returns bytes, but width must match the Type |
|
476 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())) / sizeof(Type); |
|
477 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())) / sizeof(Type); |
|
478 |
|
479 TInt r, g, b; |
|
480 TInt x, y; // Loop counters |
|
481 |
|
482 // Pitch is the number of pixels to skip before next scanline start |
|
483 TInt pitchTarget = scanWtarget - width; |
|
484 TInt pitchSource = scanWsource - width; |
|
485 |
|
486 // Prepare the data addresses |
|
487 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
488 Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() ); |
|
489 Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() ); |
|
490 |
|
491 dataS = dataS + scanWsource + 1; |
|
492 |
|
493 // Calculate the mean per pixel |
|
494 for( y = 0; y < height; y++ ) |
|
495 { |
|
496 for( x = 0; x < width; x++ ) |
|
497 { |
|
498 r = (AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource - 1)) + |
|
499 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource )) + |
|
500 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource + 1)) + |
|
501 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - 1 )) + |
|
502 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS )) + |
|
503 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + 1 )) + |
|
504 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource - 1)) + |
|
505 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource )) + |
|
506 AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource + 1))) / 9; |
|
507 |
|
508 g = (AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource - 1)) + |
|
509 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource )) + |
|
510 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource + 1)) + |
|
511 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - 1 )) + |
|
512 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS )) + |
|
513 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + 1 )) + |
|
514 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource - 1)) + |
|
515 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource )) + |
|
516 AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource + 1))) / 9; |
|
517 |
|
518 |
|
519 b = (AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource - 1)) + |
|
520 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource )) + |
|
521 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource + 1)) + |
|
522 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - 1 )) + |
|
523 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS )) + |
|
524 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + 1 )) + |
|
525 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource - 1)) + |
|
526 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource )) + |
|
527 AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource + 1))) / 9; |
|
528 |
|
529 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
530 // is supported -> negative values are shifted correctly |
|
531 r = ( r * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::R8(*dataS) ) >> 8; |
|
532 g = ( g * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::G8(*dataS) ) >> 8; |
|
533 b = ( b * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::B8(*dataS) ) >> 8; |
|
534 |
|
535 if( r < 0 ) r = 0; |
|
536 else if( r > 255 ) r = 255; |
|
537 |
|
538 if( g < 0 ) g = 0; |
|
539 else if( g > 255 ) g = 255; |
|
540 |
|
541 if( b < 0 ) b = 0; |
|
542 else if( b > 255 ) b = 255; |
|
543 |
|
544 AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(r), TUint8(g), TUint8(b) ); |
|
545 |
|
546 dataT++; |
|
547 dataS++; |
|
548 } |
|
549 |
|
550 dataT = dataT + pitchTarget; |
|
551 dataS = dataS + pitchSource; |
|
552 } |
|
553 |
|
554 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
555 } |
|
556 |
|
557 //------------------------------------------------------------------------ |
|
558 /** |
|
559 * Extracts the color channel values (red, green, blue) on a 3x3 |
|
560 * neighborhood to arrays. |
|
561 */ |
|
562 static void ExtractChannels( TUint8 aReds[9], TUint8 aGreens[9], TUint8 aBlues[9], |
|
563 const Type* aPtr, TInt aScanW ) |
|
564 { |
|
565 // Top left |
|
566 Type val = *(aPtr - aScanW - 1); |
|
567 aReds[0] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
568 aGreens[0] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
569 aBlues[0] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
570 |
|
571 // Top |
|
572 val = *(aPtr - aScanW); |
|
573 aReds[1] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
574 aGreens[1] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
575 aBlues[1] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
576 |
|
577 // Top right |
|
578 val = *(aPtr - aScanW + 1); |
|
579 aReds[2] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
580 aGreens[2] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
581 aBlues[2] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
582 |
|
583 // Left |
|
584 val = *(aPtr - 1); |
|
585 aReds[3] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
586 aGreens[3] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
587 aBlues[3] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
588 |
|
589 // Center |
|
590 val = *(aPtr); |
|
591 aReds[4] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
592 aGreens[4] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
593 aBlues[4] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
594 |
|
595 // Right |
|
596 val = *(aPtr + 1); |
|
597 aReds[5] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
598 aGreens[5] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
599 aBlues[5] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
600 |
|
601 // Bottom left |
|
602 val = *(aPtr + aScanW - 1); |
|
603 aReds[6] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
604 aGreens[6] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
605 aBlues[6] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
606 |
|
607 // Bottom |
|
608 val = *(aPtr + aScanW); |
|
609 aReds[7] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
610 aGreens[7] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
611 aBlues[7] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
612 |
|
613 // Bottom right |
|
614 val = *(aPtr + aScanW + 1); |
|
615 aReds[8] = AknsRlRgb<Type,X,R,G,B>::R8(val); |
|
616 aGreens[8] = AknsRlRgb<Type,X,R,G,B>::G8(val); |
|
617 aBlues[8] = AknsRlRgb<Type,X,R,G,B>::B8(val); |
|
618 } |
|
619 //------------------------------------------------------------------------ |
|
620 /** |
|
621 * Convolutes a bitmap by calculating the median value of a 3x3 pixel |
|
622 * neighborhood as the resulting pixel value. |
|
623 */ |
|
624 static void Median( const CFbsBitmap& aTarget, |
|
625 const CFbsBitmap& aSource, |
|
626 TInt aBlendFactor ) |
|
627 { |
|
628 TInt width = aTarget.SizeInPixels().iWidth; |
|
629 TInt height = aTarget.SizeInPixels().iHeight; |
|
630 // ScanLineLength returns bytes, but width must match the Type |
|
631 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())) / sizeof(Type); |
|
632 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())) / sizeof(Type); |
|
633 |
|
634 TInt r, g, b; |
|
635 TInt x, y; // Loop counters |
|
636 TUint8 reds[9], greens[9], blues[9]; |
|
637 |
|
638 // Pitch is the number of pixels to skip before next scanline start |
|
639 TInt pitchTarget = scanWtarget - width; |
|
640 TInt pitchSource = scanWsource - width; |
|
641 |
|
642 // Prepare the data addresses |
|
643 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
644 Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() ); |
|
645 Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() ); |
|
646 |
|
647 // Convolute the inner rect |
|
648 dataS = dataS + scanWsource + 1; |
|
649 |
|
650 for( y = 0; y < height; y++ ) |
|
651 { |
|
652 for( x = 0; x < width; x++ ) |
|
653 { |
|
654 // Median calculation is done on per channel basis, extract the |
|
655 // neighborhood channels. |
|
656 ExtractChannels(reds, greens, blues, dataS, scanWsource); |
|
657 |
|
658 // Median + exposure blending. Note: It is assumed that arithmetic |
|
659 // shifting is supported -> negative values are shifted correctly |
|
660 r = ( AknsRlUtil::Median9(reds) * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::R8(*dataS) ) >> 8; |
|
661 g = ( AknsRlUtil::Median9(greens) * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::G8(*dataS) ) >> 8; |
|
662 b = ( AknsRlUtil::Median9(blues) * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::B8(*dataS) ) >> 8; |
|
663 |
|
664 if( r < 0 ) r = 0; |
|
665 else if( r > 255 ) r = 255; |
|
666 |
|
667 if( g < 0 ) g = 0; |
|
668 else if( g > 255 ) g = 255; |
|
669 |
|
670 if( b < 0 ) b = 0; |
|
671 else if( b > 255 ) b = 255; |
|
672 |
|
673 AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(r), TUint8(g), TUint8(b) ); |
|
674 |
|
675 dataT++; |
|
676 dataS++; |
|
677 } |
|
678 |
|
679 dataT = dataT + pitchTarget; |
|
680 dataS = dataS + pitchSource; |
|
681 } |
|
682 |
|
683 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
684 } |
|
685 //------------------------------------------------------------------------ |
|
686 /** |
|
687 * Convolutes a bitmap by calculating the maximum value of a 3x3 pixel |
|
688 * neighborhood as the resulting pixel value. |
|
689 */ |
|
690 static void Max( const CFbsBitmap& aTarget, |
|
691 const CFbsBitmap& aSource, |
|
692 TInt aBlendFactor ) |
|
693 { |
|
694 TInt width = aTarget.SizeInPixels().iWidth; |
|
695 TInt height = aTarget.SizeInPixels().iHeight; |
|
696 // ScanLineLength returns bytes, but width must match the Type |
|
697 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())) / sizeof(Type); |
|
698 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())) / sizeof(Type); |
|
699 |
|
700 TInt r, g, b; |
|
701 TInt x, y; // Loop counters |
|
702 |
|
703 // Pitch is the number of pixels to skip before next scanline start |
|
704 TInt pitchTarget = scanWtarget - width; |
|
705 TInt pitchSource = scanWsource - width; |
|
706 |
|
707 // Prepare the data addresses |
|
708 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
709 Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() ); |
|
710 Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() ); |
|
711 |
|
712 // Convolute the inner rect |
|
713 dataS = dataS + scanWsource + 1; |
|
714 |
|
715 for( y = 0; y < height; y++ ) |
|
716 { |
|
717 for( x = 0; x < width; x++ ) |
|
718 { |
|
719 r = AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource - 1 )); |
|
720 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource )), r ); |
|
721 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource + 1)), r ); |
|
722 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - 1 )), r ); |
|
723 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS )), r ); |
|
724 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + 1 )), r ); |
|
725 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource - 1)), r ); |
|
726 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource )), r ); |
|
727 r = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource + 1)), r ); |
|
728 |
|
729 g = AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource - 1 )); |
|
730 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource )), g ); |
|
731 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource + 1)), g ); |
|
732 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - 1 )), g ); |
|
733 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS )), g ); |
|
734 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + 1 )), g ); |
|
735 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource - 1)), g ); |
|
736 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource )), g ); |
|
737 g = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource + 1)), g ); |
|
738 |
|
739 |
|
740 b = AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource - 1 )); |
|
741 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource )), b ); |
|
742 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource + 1)), b ); |
|
743 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - 1 )), b ); |
|
744 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS )), b ); |
|
745 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + 1 )), b ); |
|
746 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource - 1)), b ); |
|
747 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource )), b ); |
|
748 b = AknsRlUtil::Max( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource + 1)), b ); |
|
749 |
|
750 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
751 // is supported -> negative values are shifted correctly |
|
752 r = ( r * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::R8(*dataS) ) >> 8; |
|
753 g = ( g * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::G8(*dataS) ) >> 8; |
|
754 b = ( b * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::B8(*dataS) ) >> 8; |
|
755 |
|
756 if( r < 0 ) r = 0; |
|
757 else if( r > 255 ) r = 255; |
|
758 |
|
759 if( g < 0 ) g = 0; |
|
760 else if( g > 255 ) g = 255; |
|
761 |
|
762 if( b < 0 ) b = 0; |
|
763 else if( b > 255 ) b = 255; |
|
764 |
|
765 AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(r), TUint8(g), TUint8(b) ); |
|
766 |
|
767 dataT++; |
|
768 dataS++; |
|
769 } |
|
770 |
|
771 dataT = dataT + pitchTarget; |
|
772 dataS = dataS + pitchSource; |
|
773 } |
|
774 |
|
775 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
776 } |
|
777 //------------------------------------------------------------------------ |
|
778 /** |
|
779 * Convolutes a bitmap by calculating the minimum value of a 3x3 pixel |
|
780 * neighborhood as the resulting pixel value. |
|
781 */ |
|
782 static void Min( const CFbsBitmap& aTarget, |
|
783 const CFbsBitmap& aSource, |
|
784 TInt aBlendFactor ) |
|
785 { |
|
786 TInt width = aTarget.SizeInPixels().iWidth; |
|
787 TInt height = aTarget.SizeInPixels().iHeight; |
|
788 // ScanLineLength returns bytes, but width must match the Type |
|
789 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())) / sizeof(Type); |
|
790 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())) / sizeof(Type); |
|
791 |
|
792 TInt r, g, b; |
|
793 TInt x, y; // Loop counters |
|
794 |
|
795 // Pitch is the number of pixels to skip before next scanline start |
|
796 TInt pitchTarget = scanWtarget - width; |
|
797 TInt pitchSource = scanWsource - width; |
|
798 |
|
799 // Prepare the data addresses |
|
800 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
801 Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() ); |
|
802 Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() ); |
|
803 |
|
804 // Convolute the inner rect |
|
805 dataS = dataS + scanWsource + 1; |
|
806 |
|
807 for( y = 0; y < height; y++ ) |
|
808 { |
|
809 for( x = 0; x < width; x++ ) |
|
810 { |
|
811 r = AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource - 1 )); |
|
812 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource )), r ); |
|
813 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - scanWsource + 1)), r ); |
|
814 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS - 1 )), r ); |
|
815 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS )), r ); |
|
816 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + 1 )), r ); |
|
817 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource - 1)), r ); |
|
818 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource )), r ); |
|
819 r = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::R8(*(dataS + scanWsource + 1)), r ); |
|
820 |
|
821 g = AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource - 1 )); |
|
822 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource )), g ); |
|
823 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - scanWsource + 1)), g ); |
|
824 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS - 1 )), g ); |
|
825 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS )), g ); |
|
826 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + 1 )), g ); |
|
827 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource - 1)), g ); |
|
828 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource )), g ); |
|
829 g = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::G8(*(dataS + scanWsource + 1)), g ); |
|
830 |
|
831 |
|
832 b = AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource - 1 )); |
|
833 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource )), b ); |
|
834 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - scanWsource + 1)), b ); |
|
835 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS - 1 )), b ); |
|
836 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS )), b ); |
|
837 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + 1 )), b ); |
|
838 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource - 1)), b ); |
|
839 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource )), b ); |
|
840 b = AknsRlUtil::Min( AknsRlRgb<Type,X,R,G,B>::B8(*(dataS + scanWsource + 1)), b ); |
|
841 |
|
842 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
843 // is supported -> negative values are shifted correctly |
|
844 r = ( r * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::R8(*dataS) ) >> 8; |
|
845 g = ( g * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::G8(*dataS) ) >> 8; |
|
846 b = ( b * aBlendFactor + (255 - aBlendFactor) * AknsRlRgb<Type,X,R,G,B>::B8(*dataS) ) >> 8; |
|
847 |
|
848 if( r < 0 ) r = 0; |
|
849 else if( r > 255 ) r = 255; |
|
850 |
|
851 if( g < 0 ) g = 0; |
|
852 else if( g > 255 ) g = 255; |
|
853 |
|
854 if( b < 0 ) b = 0; |
|
855 else if( b > 255 ) b = 255; |
|
856 |
|
857 AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(r), TUint8(g), TUint8(b) ); |
|
858 |
|
859 dataT++; |
|
860 dataS++; |
|
861 } |
|
862 |
|
863 dataT = dataT + pitchTarget; |
|
864 dataS = dataS + pitchSource; |
|
865 } |
|
866 |
|
867 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
868 } |
|
869 }; // End of AknsRlEffectConvolution |
|
870 |
|
871 // =================== GRAYSCALE IMPL. OF CONVOLUTION ========================== |
|
872 /** |
|
873 * Implementation of grayscale convolutions. The code is similar to templated |
|
874 * RGB versions above, the main difference is that only one channel value (gray) |
|
875 * is processed per pixel. |
|
876 */ |
|
877 class AknsRlEffectConvolutionGray |
|
878 { |
|
879 public: |
|
880 //------------------------------------------------------------------------ |
|
881 static void Kernel( const CFbsBitmap& aTarget, |
|
882 const CFbsBitmap& aSource, |
|
883 const TInt aKernel[9], |
|
884 const TInt aBlendFactor, |
|
885 const TInt aBias ) |
|
886 { |
|
887 TInt width = aTarget.SizeInPixels().iWidth; |
|
888 TInt height = aTarget.SizeInPixels().iHeight; |
|
889 // CFbsBitmap::ScanLineLength returns bytes |
|
890 TInt scanWtarget = CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode()); |
|
891 TInt scanWsource = CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode()); |
|
892 |
|
893 TInt kernelSum = aKernel[0] + aKernel[1] + aKernel[2] + |
|
894 aKernel[3] + aKernel[4] + aKernel[5] + |
|
895 aKernel[6] + aKernel[7] + aKernel[8]; |
|
896 |
|
897 if( 0 == kernelSum ) |
|
898 kernelSum = 1; |
|
899 |
|
900 TInt shade; |
|
901 TInt x, y; // Loop counters |
|
902 |
|
903 // Pitch is the number of pixels to skip before next scanline start |
|
904 TInt pitchTarget = scanWtarget - width; |
|
905 TInt pitchSource = scanWsource - width; |
|
906 |
|
907 // Prepare the data addresses |
|
908 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
909 TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() ); |
|
910 TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() ); |
|
911 |
|
912 dataS = dataS + scanWsource + 1; |
|
913 |
|
914 for( y = 0; y < height; y++ ) |
|
915 { |
|
916 for( x = 0; x < width; x++ ) |
|
917 { |
|
918 shade = aBias + (*(dataS - scanWsource - 1) * aKernel[0] + |
|
919 *(dataS - scanWsource ) * aKernel[1] + |
|
920 *(dataS - scanWsource + 1) * aKernel[2] + |
|
921 *(dataS - 1 ) * aKernel[3] + |
|
922 *(dataS ) * aKernel[4] + |
|
923 *(dataS + 1 ) * aKernel[5] + |
|
924 *(dataS + scanWsource - 1) * aKernel[6] + |
|
925 *(dataS + scanWsource ) * aKernel[7] + |
|
926 *(dataS + scanWsource + 1) * aKernel[8]) / kernelSum; |
|
927 |
|
928 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
929 // is supported -> negative values are shifted correctly |
|
930 shade = ( shade * aBlendFactor + (255 - aBlendFactor) * (*dataS) ) >> 8; //lint !e702 Arithmetic shifting assumed |
|
931 |
|
932 if( shade < 0 ) |
|
933 *dataT = 0; |
|
934 else if( shade > 255 ) |
|
935 *dataT = 255; |
|
936 else |
|
937 *dataT = TUint8(shade); |
|
938 |
|
939 dataT++; |
|
940 dataS++; |
|
941 } |
|
942 |
|
943 dataT = dataT + pitchTarget; |
|
944 dataS = dataS + pitchSource; |
|
945 } |
|
946 |
|
947 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
948 } |
|
949 //------------------------------------------------------------------------ |
|
950 /** |
|
951 * "Convolutes" a bitmap with adjustable gaussian blur kernel. |
|
952 * Kernel size from 3*3 to 33*33 (odd sizes). |
|
953 */ |
|
954 static void AdjustableGaussian( const CFbsBitmap& aTarget, |
|
955 const CFbsBitmap& aSource, |
|
956 TUint16* aColumnBuffer, |
|
957 const TInt aKernelsize ) |
|
958 { |
|
959 TInt width = aTarget.SizeInPixels().iWidth; |
|
960 TInt height = aTarget.SizeInPixels().iHeight; |
|
961 // ScanLineLength returns bytes, but width must match the Type |
|
962 TInt scanWtarget = (CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode())); |
|
963 TInt scanWsource = (CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode())); |
|
964 |
|
965 TUint16 shade; |
|
966 TInt x, y, i; // Loop counters |
|
967 |
|
968 // Pitch is the number of pixels to skip before next scanline start |
|
969 TInt pitchTarget = scanWtarget - width; |
|
970 TInt pitchSource = scanWsource - width; |
|
971 |
|
972 // Prepare the data addresses |
|
973 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
974 TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() ); |
|
975 TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() ); |
|
976 TUint8* dataR = dataT; // for recursive iterations, both source and target are the same |
|
977 dataS = dataS + scanWsource + 1; // state machine takes pixel (1,1) and output goes to pixel (0,0) |
|
978 |
|
979 TUint16 tmp1; |
|
980 TUint16 tmp2; |
|
981 |
|
982 // row buffer variables |
|
983 TUint16 SR0; |
|
984 TUint16 SR1; |
|
985 |
|
986 TInt col0_Index; // index for row 0 columns in aColumnBuffer |
|
987 TInt col1_Index; // index for row 1 columns in aColumnBuffer |
|
988 |
|
989 for ( i = 0; i < (aKernelsize - 1) >> 1 ; i++ ) // do (N-1) / 2 times |
|
990 { |
|
991 |
|
992 for( y = 0; y < (height - 1); y++ ) |
|
993 { |
|
994 SR0 = (TUint16)*dataS; // initialize row buffer variables |
|
995 SR1 = (TUint16)*dataS; |
|
996 col0_Index = 0; // initialize indexes for column buffers |
|
997 col1_Index = width; |
|
998 |
|
999 for( x = 0; x < (width - 1); x++ ) |
|
1000 { |
|
1001 tmp1 = (TUint16)*dataS; |
|
1002 tmp2 = (TUint16)(SR0 + tmp1); |
|
1003 SR0 = tmp1; |
|
1004 tmp1 = (TUint16)(SR1 + tmp2); |
|
1005 SR1 = tmp2; |
|
1006 |
|
1007 tmp2 = (TUint16)(aColumnBuffer[col0_Index] + tmp1); |
|
1008 aColumnBuffer[col0_Index++] = tmp1; |
|
1009 shade = (TUint16)((8 + aColumnBuffer[col1_Index] + tmp2) >> 4); |
|
1010 aColumnBuffer[col1_Index++] = tmp2; |
|
1011 |
|
1012 if( shade > 255 ) shade = 255; |
|
1013 *dataT = (TUint8)shade; |
|
1014 |
|
1015 dataT++; |
|
1016 dataS++; |
|
1017 } |
|
1018 |
|
1019 dataT = dataT + pitchTarget + 1; |
|
1020 dataS = dataS + pitchSource + 1; |
|
1021 } |
|
1022 dataT = dataR; // for more than 1 iterations, use target bitmap for both |
|
1023 dataS = dataR+scanWtarget+1; // target and source |
|
1024 } |
|
1025 |
|
1026 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1027 } |
|
1028 |
|
1029 //------------------------------------------------------------------------ |
|
1030 static void Mean( const CFbsBitmap& aTarget, |
|
1031 const CFbsBitmap& aSource, |
|
1032 TInt aBlendFactor ) |
|
1033 { |
|
1034 TInt width = aTarget.SizeInPixels().iWidth; |
|
1035 TInt height = aTarget.SizeInPixels().iHeight; |
|
1036 // CFbsBitmap::ScanLineLength returns bytes |
|
1037 TInt scanWtarget = CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode()); |
|
1038 TInt scanWsource = CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode()); |
|
1039 |
|
1040 TInt shade; |
|
1041 TInt x, y; // Loop counters |
|
1042 |
|
1043 // Pitch is the number of pixels to skip before next scanline start |
|
1044 TInt pitchTarget = scanWtarget - width; |
|
1045 TInt pitchSource = scanWsource - width; |
|
1046 |
|
1047 // Prepare the data addresses |
|
1048 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
1049 TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() ); |
|
1050 TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() ); |
|
1051 |
|
1052 // Convolute the inner rect |
|
1053 dataS = dataS + scanWsource + 1; |
|
1054 |
|
1055 for( y = 0; y < height; y++ ) |
|
1056 { |
|
1057 for( x = 0; x < width; x++ ) |
|
1058 { |
|
1059 shade = (*(dataS - scanWsource - 1) + |
|
1060 *(dataS - scanWsource ) + |
|
1061 *(dataS - scanWsource + 1) + |
|
1062 *(dataS - 1 ) + |
|
1063 *(dataS ) + |
|
1064 *(dataS + 1 ) + |
|
1065 *(dataS + scanWsource - 1) + |
|
1066 *(dataS + scanWsource ) + |
|
1067 *(dataS + scanWsource + 1)) / 9; |
|
1068 |
|
1069 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
1070 // is supported -> negative values are shifted correctly |
|
1071 shade = ( shade * aBlendFactor + (255 - aBlendFactor) * (*dataS) ) >> 8; |
|
1072 |
|
1073 if( shade < 0 ) |
|
1074 *dataT = 0; |
|
1075 else if( shade > 255 ) |
|
1076 *dataT = 255; |
|
1077 else |
|
1078 *dataT = TUint8(shade); |
|
1079 |
|
1080 dataT++; |
|
1081 dataS++; |
|
1082 } |
|
1083 |
|
1084 dataT = dataT + pitchTarget; |
|
1085 dataS = dataS + pitchSource; |
|
1086 } |
|
1087 |
|
1088 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1089 } |
|
1090 //------------------------------------------------------------------------ |
|
1091 /** |
|
1092 * Collects the shades on a 3x3 neighborhood to array. |
|
1093 */ |
|
1094 static void ExtractShades( TUint8 aShades[9], const TUint8* aPtr, TInt aScanW ) |
|
1095 { |
|
1096 aShades[0] = *(aPtr - aScanW - 1); // Top left |
|
1097 aShades[1] = *(aPtr - aScanW); // Top |
|
1098 aShades[2] = *(aPtr - aScanW + 1); // Top right |
|
1099 aShades[3] = *(aPtr - 1); // Left |
|
1100 aShades[4] = *(aPtr); // Center |
|
1101 aShades[5] = *(aPtr + 1); // Right |
|
1102 aShades[6] = *(aPtr + aScanW - 1); // Bottom left |
|
1103 aShades[7] = *(aPtr + aScanW); // Bottom |
|
1104 aShades[8] = *(aPtr + aScanW + 1); // Bottom right |
|
1105 } |
|
1106 //------------------------------------------------------------------------ |
|
1107 static void Median( const CFbsBitmap& aTarget, |
|
1108 const CFbsBitmap& aSource, |
|
1109 TInt aBlendFactor ) |
|
1110 { |
|
1111 TInt width = aTarget.SizeInPixels().iWidth; |
|
1112 TInt height = aTarget.SizeInPixels().iHeight; |
|
1113 // CFbsBitmap::ScanLineLength returns bytes |
|
1114 TInt scanWtarget = CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode()); |
|
1115 TInt scanWsource = CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode()); |
|
1116 |
|
1117 TInt shade; |
|
1118 TInt x, y; // Loop counters |
|
1119 TUint8 shades[9]; |
|
1120 |
|
1121 // Pitch is the number of pixels to skip before next scanline start |
|
1122 TInt pitchTarget = scanWtarget - width; |
|
1123 TInt pitchSource = scanWsource - width; |
|
1124 |
|
1125 // Prepare the data addresses |
|
1126 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
1127 TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() ); |
|
1128 TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() ); |
|
1129 |
|
1130 // Convolute the inner rect |
|
1131 dataS = dataS + scanWsource + 1; |
|
1132 |
|
1133 for( y = 0; y < height; y++ ) |
|
1134 { |
|
1135 for( x = 0; x < width; x++ ) |
|
1136 { |
|
1137 ExtractShades(shades, dataS, scanWsource); |
|
1138 |
|
1139 // Median + exposure blending. Note: It is assumed that arithmetic |
|
1140 // shifting is supported -> negative values are shifted correctly |
|
1141 shade = ( AknsRlUtil::Median9(shades) * aBlendFactor + (255 - aBlendFactor) * (*dataS) ) >> 8; |
|
1142 |
|
1143 if( shade < 0 ) |
|
1144 *dataT = 0; |
|
1145 else if( shade > 255 ) |
|
1146 *dataT = 255; |
|
1147 else |
|
1148 *dataT = TUint8(shade); |
|
1149 |
|
1150 dataT++; |
|
1151 dataS++; |
|
1152 } |
|
1153 |
|
1154 dataT = dataT + pitchTarget; |
|
1155 dataS = dataS + pitchSource; |
|
1156 } |
|
1157 |
|
1158 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1159 } |
|
1160 //------------------------------------------------------------------------ |
|
1161 static void Max( const CFbsBitmap& aTarget, |
|
1162 const CFbsBitmap& aSource, |
|
1163 TInt aBlendFactor ) |
|
1164 { |
|
1165 TInt width = aTarget.SizeInPixels().iWidth; |
|
1166 TInt height = aTarget.SizeInPixels().iHeight; |
|
1167 // CFbsBitmap::ScanLineLength returns bytes |
|
1168 TInt scanWtarget = CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode()); |
|
1169 TInt scanWsource = CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode()); |
|
1170 |
|
1171 TInt shade; |
|
1172 TInt x, y; // Loop counters |
|
1173 |
|
1174 // Pitch is the number of pixels to skip before next scanline start |
|
1175 TInt pitchTarget = scanWtarget - width; |
|
1176 TInt pitchSource = scanWsource - width; |
|
1177 |
|
1178 // Prepare the data addresses |
|
1179 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
1180 TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() ); |
|
1181 TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() ); |
|
1182 |
|
1183 // Convolute the inner rect |
|
1184 dataS = dataS + scanWsource + 1; |
|
1185 |
|
1186 for( y = 0; y < height; y++ ) |
|
1187 { |
|
1188 for( x = 0; x < width; x++ ) |
|
1189 { |
|
1190 shade = *(dataS - scanWsource - 1 ); |
|
1191 shade = AknsRlUtil::Max( *(dataS - scanWsource ), shade ); |
|
1192 shade = AknsRlUtil::Max( *(dataS - scanWsource + 1), shade ); |
|
1193 shade = AknsRlUtil::Max( *(dataS - 1 ), shade ); |
|
1194 shade = AknsRlUtil::Max( *(dataS ), shade ); |
|
1195 shade = AknsRlUtil::Max( *(dataS + 1 ), shade ); |
|
1196 shade = AknsRlUtil::Max( *(dataS + scanWsource - 1), shade ); |
|
1197 shade = AknsRlUtil::Max( *(dataS + scanWsource ), shade ); |
|
1198 shade = AknsRlUtil::Max( *(dataS + scanWsource + 1), shade ); |
|
1199 |
|
1200 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
1201 // is supported -> negative values are shifted correctly |
|
1202 shade = ( shade * aBlendFactor + (255 - aBlendFactor) * (*dataS) ) >> 8; |
|
1203 |
|
1204 if( shade < 0 ) |
|
1205 *dataT = 0; |
|
1206 else if( shade > 255 ) |
|
1207 *dataT = 255; |
|
1208 else |
|
1209 *dataT = TUint8(shade); |
|
1210 |
|
1211 dataT++; |
|
1212 dataS++; |
|
1213 } |
|
1214 |
|
1215 dataT = dataT + pitchTarget; |
|
1216 dataS = dataS + pitchSource; |
|
1217 } |
|
1218 |
|
1219 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1220 } |
|
1221 //------------------------------------------------------------------------ |
|
1222 static void Min( const CFbsBitmap& aTarget, |
|
1223 const CFbsBitmap& aSource, |
|
1224 TInt aBlendFactor ) |
|
1225 { |
|
1226 TInt width = aTarget.SizeInPixels().iWidth; |
|
1227 TInt height = aTarget.SizeInPixels().iHeight; |
|
1228 // CFbsBitmap::ScanLineLength returns bytes |
|
1229 TInt scanWtarget = CFbsBitmap::ScanLineLength(aTarget.SizeInPixels().iWidth, aTarget.DisplayMode()); |
|
1230 TInt scanWsource = CFbsBitmap::ScanLineLength(aSource.SizeInPixels().iWidth, aSource.DisplayMode()); |
|
1231 |
|
1232 TInt shade; |
|
1233 TInt x, y; // Loop counters |
|
1234 |
|
1235 // Pitch is the number of pixels to skip before next scanline start |
|
1236 TInt pitchTarget = scanWtarget - width; |
|
1237 TInt pitchSource = scanWsource - width; |
|
1238 |
|
1239 // Prepare the data addresses |
|
1240 aTarget.LockHeap( ETrue ); // Lock the global bitmap heap |
|
1241 TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() ); |
|
1242 TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() ); |
|
1243 |
|
1244 // Convolute the inner rect |
|
1245 dataS = dataS + scanWsource + 1; |
|
1246 |
|
1247 for( y = 0; y < height; y++ ) |
|
1248 { |
|
1249 for( x = 0; x < width; x++ ) |
|
1250 { |
|
1251 shade = *(dataS - scanWsource - 1 ); |
|
1252 shade = AknsRlUtil::Min( *(dataS - scanWsource ), shade ); |
|
1253 shade = AknsRlUtil::Min( *(dataS - scanWsource + 1), shade ); |
|
1254 shade = AknsRlUtil::Min( *(dataS - 1 ), shade ); |
|
1255 shade = AknsRlUtil::Min( *(dataS ), shade ); |
|
1256 shade = AknsRlUtil::Min( *(dataS + 1 ), shade ); |
|
1257 shade = AknsRlUtil::Min( *(dataS + scanWsource - 1), shade ); |
|
1258 shade = AknsRlUtil::Min( *(dataS + scanWsource ), shade ); |
|
1259 shade = AknsRlUtil::Min( *(dataS + scanWsource + 1), shade ); |
|
1260 |
|
1261 // Exposure blending. Note: It is assumed that arithmetic shifting |
|
1262 // is supported -> negative values are shifted correctly |
|
1263 shade = ( shade * aBlendFactor + (255 - aBlendFactor) * (*dataS) ) >> 8; //lint !e702 Arithmetic shifting assumed |
|
1264 |
|
1265 if( shade < 0 ) |
|
1266 *dataT = 0; |
|
1267 else if( shade > 255 ) |
|
1268 *dataT = 255; |
|
1269 else |
|
1270 *dataT = TUint8(shade); |
|
1271 |
|
1272 dataT++; |
|
1273 dataS++; |
|
1274 } |
|
1275 |
|
1276 dataT = dataT + pitchTarget; |
|
1277 dataS = dataS + pitchSource; |
|
1278 } |
|
1279 |
|
1280 aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1281 } |
|
1282 }; // End of AknsRlEffectConvolutionGray |
|
1283 |
|
1284 // ============================ MEMBER FUNCTIONS =============================== |
|
1285 |
|
1286 // ----------------------------------------------------------------------------- |
|
1287 // CAknsRlEffectPluginConvolution::CAknsRlEffectPluginConvolution |
|
1288 // C++ default constructor can NOT contain any code, that |
|
1289 // might leave. |
|
1290 // ----------------------------------------------------------------------------- |
|
1291 // |
|
1292 CAknsRlEffectPluginConvolution::CAknsRlEffectPluginConvolution() |
|
1293 { |
|
1294 } |
|
1295 |
|
1296 // ----------------------------------------------------------------------------- |
|
1297 // Destructor |
|
1298 // ----------------------------------------------------------------------------- |
|
1299 // |
|
1300 CAknsRlEffectPluginConvolution::~CAknsRlEffectPluginConvolution() |
|
1301 { |
|
1302 iContext = NULL; // Removes lint nag |
|
1303 iColumnBuffer = NULL; // Removes lint nag |
|
1304 } |
|
1305 |
|
1306 // ----------------------------------------------------------------------------- |
|
1307 // CAknsRlEffectPluginConvolution::EffectUid |
|
1308 // ----------------------------------------------------------------------------- |
|
1309 // |
|
1310 TUid CAknsRlEffectPluginConvolution::EffectUid() const |
|
1311 { |
|
1312 return TUid::Uid( KAknsRlEffectPluginConvolutionUID ); |
|
1313 } |
|
1314 |
|
1315 // ----------------------------------------------------------------------------- |
|
1316 // CAknsRlEffectPluginConvolution::Effect |
|
1317 // ----------------------------------------------------------------------------- |
|
1318 // |
|
1319 MAknsRlEffect* CAknsRlEffectPluginConvolution::Effect( const TInt aInterface ) |
|
1320 { |
|
1321 if( aInterface == KAknsRlEffectPluginInterfaceEffect ) |
|
1322 return this; |
|
1323 return NULL; |
|
1324 } |
|
1325 |
|
1326 // ----------------------------------------------------------------------------- |
|
1327 // CAknsRlEffectPluginConvolution::InitializeL |
|
1328 // ----------------------------------------------------------------------------- |
|
1329 // |
|
1330 void CAknsRlEffectPluginConvolution::InitializeL() |
|
1331 { |
|
1332 iContext = NULL; |
|
1333 } |
|
1334 |
|
1335 // ----------------------------------------------------------------------------- |
|
1336 // CAknsRlEffectPluginConvolution::Release |
|
1337 // ----------------------------------------------------------------------------- |
|
1338 // |
|
1339 void CAknsRlEffectPluginConvolution::Release() |
|
1340 { |
|
1341 } |
|
1342 |
|
1343 // ----------------------------------------------------------------------------- |
|
1344 // CAknsRlEffectPluginConvolution::ActivateL |
|
1345 // ----------------------------------------------------------------------------- |
|
1346 // |
|
1347 void CAknsRlEffectPluginConvolution::ActivateL( MAknsRlEffectContext* aContext ) |
|
1348 { |
|
1349 if( !aContext ) // We absolutely need the context |
|
1350 { |
|
1351 User::Leave( KErrArgument ); |
|
1352 } |
|
1353 |
|
1354 iContext = aContext; |
|
1355 |
|
1356 iMode = EModeEdge; |
|
1357 iBlendFactor = 255; |
|
1358 iGaussianBlurSize = 3; |
|
1359 } |
|
1360 |
|
1361 // ----------------------------------------------------------------------------- |
|
1362 // CAknsRlEffectPluginConvolution::Deactivate |
|
1363 // ----------------------------------------------------------------------------- |
|
1364 // |
|
1365 void CAknsRlEffectPluginConvolution::Deactivate() |
|
1366 { |
|
1367 } |
|
1368 |
|
1369 // ----------------------------------------------------------------------------- |
|
1370 // CAknsRlEffectPluginConvolution::SetParametersL |
|
1371 // ----------------------------------------------------------------------------- |
|
1372 // |
|
1373 void CAknsRlEffectPluginConvolution::SetParametersL( MAknsRlParameterIterator& aParameters ) |
|
1374 { |
|
1375 // Iterate over available parameters |
|
1376 while( aParameters.HasNext() ) |
|
1377 { |
|
1378 const TAknsRlParameterData* param = aParameters.NextL(); |
|
1379 |
|
1380 // Fetch mode value |
|
1381 if( param->iName->Compare( KAknsRlEffectConvolutionMode ) == 0 ) |
|
1382 { |
|
1383 if( param->iType != EAknsRlParameterTypeNumber ) |
|
1384 User::Leave( KErrArgument ); |
|
1385 |
|
1386 if( param->iNumber < EModeEdge || param->iNumber > EModeAdjustableGaussian ) |
|
1387 User::Leave( KErrArgument ); |
|
1388 |
|
1389 iMode = param->iNumber; |
|
1390 } |
|
1391 // Fetch blend factor value |
|
1392 else if( param->iName->Compare( KAknsRlEffectConvolutionBlendFactor ) == 0 ) |
|
1393 { |
|
1394 if( param->iType != EAknsRlParameterTypeNumber ) |
|
1395 User::Leave( KErrArgument ); |
|
1396 |
|
1397 iBlendFactor = param->iNumber; |
|
1398 } |
|
1399 // Fetch adjustable gaussian blur size |
|
1400 else if( param->iName->Compare( KAknsRlEffectConvolutionGaussianBlurSize ) == 0 ) |
|
1401 { |
|
1402 if( param->iType != EAknsRlParameterTypeNumber ) |
|
1403 User::Leave( KErrArgument ); |
|
1404 |
|
1405 // only odd sizes allowed |
|
1406 if ( param->iNumber < 3 || |
|
1407 param->iNumber > 55 || |
|
1408 !(param->iNumber&1) ) |
|
1409 User::Leave( KErrArgument ); |
|
1410 iGaussianBlurSize = param->iNumber; |
|
1411 } |
|
1412 } |
|
1413 } |
|
1414 |
|
1415 // ----------------------------------------------------------------------------- |
|
1416 // CAknsRlEffectPluginConvolution::GetCapabilities |
|
1417 // ----------------------------------------------------------------------------- |
|
1418 // |
|
1419 void CAknsRlEffectPluginConvolution::GetCapabilities( TAknsRlEffectCaps& aCaps ) |
|
1420 { |
|
1421 aCaps.iOutputLayerSupport = KAknsRlLayerRGBOnly; |
|
1422 aCaps.iInputLayerASupport = KAknsRlLayerRGBOnly; |
|
1423 aCaps.iInputLayerBSupport = KAknsRlLayerNone; |
|
1424 } |
|
1425 |
|
1426 // ----------------------------------------------------------------------------- |
|
1427 // CAknsRlEffectPluginConvolution::Render |
|
1428 // ----------------------------------------------------------------------------- |
|
1429 // |
|
1430 TInt CAknsRlEffectPluginConvolution::Render( const TAknsRlRenderOpParam& aParam ) |
|
1431 { |
|
1432 if( !iContext ) // We absolutely need the context |
|
1433 { |
|
1434 return KErrBadHandle; |
|
1435 } |
|
1436 |
|
1437 // To do anything we need both, the output layer and input layer |
|
1438 if( ( aParam.iOutputLayerStatus & KAknsRlLayerRGBOnly ) && |
|
1439 ( aParam.iInputLayerAStatus & KAknsRlLayerRGBOnly ) ) |
|
1440 { |
|
1441 // Query the layers, uninitialized because we process the whole image |
|
1442 TAknsRlLayerData dataTarget; |
|
1443 TRAPD( err, iContext->GetLayerDataL( dataTarget, aParam.iOutputLayerIndex, |
|
1444 aParam.iOutputLayerStatus, EFalse ) ); |
|
1445 if( KErrNone != err ) |
|
1446 return KErrArgument; |
|
1447 |
|
1448 TAknsRlLayerData dataSource; |
|
1449 TRAP( err, iContext->GetLayerDataL( dataSource, aParam.iInputLayerAIndex, |
|
1450 aParam.iInputLayerAStatus, EFalse ) ); |
|
1451 if( KErrNone != err ) |
|
1452 return KErrArgument; |
|
1453 |
|
1454 if( !dataTarget.iRGBBitmap ) // We need the target bitmap |
|
1455 return KErrBadHandle; |
|
1456 |
|
1457 if( !dataSource.iRGBBitmap ) // We need the source bitmap |
|
1458 return KErrBadHandle; |
|
1459 |
|
1460 CFbsBitmap& t = *(dataTarget.iRGBBitmap); |
|
1461 CFbsBitmap& s = *(dataSource.iRGBBitmap); |
|
1462 |
|
1463 TDisplayMode modeT = t.DisplayMode(); |
|
1464 TDisplayMode modeS = s.DisplayMode(); |
|
1465 |
|
1466 TInt sWidth = s.SizeInPixels().iWidth; |
|
1467 TInt sHeight = s.SizeInPixels().iHeight; |
|
1468 |
|
1469 // adjustable gaussian blur is a special case, which doesn't need |
|
1470 // temporary bitmap, so this must be handled before other convolution |
|
1471 // filters |
|
1472 if ( TMode( iMode ) == EModeAdjustableGaussian) |
|
1473 { |
|
1474 // first try to allocate space for row and column data buffers |
|
1475 |
|
1476 TInt rgbUsed = 3; |
|
1477 if( EGray256 == modeT && EGray256 == modeS ) |
|
1478 rgbUsed = 1; // no need for extra buffer for rgb components |
|
1479 |
|
1480 // 2 rows in sWidth columns, 3 times for rgb pictures |
|
1481 iColumnBuffer = new TUint16[2*sWidth*rgbUsed]; // OOM returns NULL |
|
1482 if ( !iColumnBuffer ) |
|
1483 return KErrNoMemory; |
|
1484 |
|
1485 for (int i=0; i<2*sWidth*rgbUsed ; i++) |
|
1486 iColumnBuffer[i] = 0; // empty buffer |
|
1487 |
|
1488 if( EColor64K == modeT && EColor64K == modeS ) |
|
1489 AknsRlEffectConvolution<TUint16,0,5,6,5>::AdjustableGaussian( t, s, iColumnBuffer, iGaussianBlurSize ); |
|
1490 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1491 AknsRlEffectConvolution<TUint32,8,8,8,8>::AdjustableGaussian( t, s, iColumnBuffer, iGaussianBlurSize ); |
|
1492 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1493 AknsRlEffectConvolutionGray::AdjustableGaussian( t, s, iColumnBuffer, iGaussianBlurSize ); |
|
1494 else |
|
1495 return KErrArgument; |
|
1496 |
|
1497 delete [] iColumnBuffer; |
|
1498 return KErrNone; |
|
1499 } |
|
1500 |
|
1501 |
|
1502 |
|
1503 // for convolution we need source bitmap that is 2 pixels wider and |
|
1504 // higher than target (because we need to convolute border pixels) |
|
1505 // this also removes the need to backup source pixels if source |
|
1506 // and target bitmaps are the same |
|
1507 CFbsBitmap* sNew = NULL; |
|
1508 sNew = new CFbsBitmap(); // OOM returns NULL |
|
1509 if( !sNew ) |
|
1510 return KErrNoMemory; |
|
1511 const CFbsBitmap& sTmp = *sNew; |
|
1512 |
|
1513 TInt bmpError = sNew->Create(TSize(sWidth+2,sHeight+2),modeS); |
|
1514 if (bmpError != KErrNone) // if there was some error in creating new bitmap |
|
1515 { |
|
1516 delete sNew; |
|
1517 return bmpError; |
|
1518 } |
|
1519 |
|
1520 // CFbsBitmap::ScanLineLength returns bytes |
|
1521 TInt originalSourceScanW = CFbsBitmap::ScanLineLength( |
|
1522 s.SizeInPixels().iWidth, |
|
1523 s.DisplayMode()); |
|
1524 TInt convoSourceScanW = CFbsBitmap::ScanLineLength( |
|
1525 sTmp.SizeInPixels().iWidth, |
|
1526 sTmp.DisplayMode()); |
|
1527 |
|
1528 // Prepare the data addresses |
|
1529 s.LockHeap( ETrue ); // Lock the global bitmap heap |
|
1530 TUint* originalSourceAddr = reinterpret_cast<TUint*>( s.DataAddress() ); |
|
1531 TUint* convoSourceAddr = reinterpret_cast<TUint*>( sTmp.DataAddress() ); |
|
1532 |
|
1533 switch( modeS ) |
|
1534 { |
|
1535 case EColor64K: |
|
1536 { |
|
1537 AMakeConvoluteSource64K(convoSourceAddr, |
|
1538 originalSourceAddr, |
|
1539 convoSourceScanW, |
|
1540 originalSourceScanW, |
|
1541 sWidth, |
|
1542 sHeight); |
|
1543 s.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1544 break; |
|
1545 } |
|
1546 case EColor16MU: |
|
1547 { |
|
1548 AMakeConvoluteSource16MU(convoSourceAddr, |
|
1549 originalSourceAddr, |
|
1550 convoSourceScanW, |
|
1551 originalSourceScanW, |
|
1552 sWidth, |
|
1553 sHeight); |
|
1554 s.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1555 break; |
|
1556 } |
|
1557 case EGray256: |
|
1558 { |
|
1559 AMakeConvoluteSource256(convoSourceAddr, |
|
1560 originalSourceAddr, |
|
1561 convoSourceScanW, |
|
1562 originalSourceScanW, |
|
1563 sWidth, |
|
1564 sHeight); |
|
1565 s.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1566 break; |
|
1567 } |
|
1568 default: |
|
1569 { |
|
1570 s.UnlockHeap( ETrue ); // Unlock the global bitmap heap |
|
1571 return KErrArgument; |
|
1572 } |
|
1573 } |
|
1574 |
|
1575 |
|
1576 #if !defined(ARM_VERSION) // separate switch-case for WINS and ARMI versions |
|
1577 switch( TMode( iMode ) ) |
|
1578 { |
|
1579 // Convolution kernel modes |
|
1580 case EModeEdge: |
|
1581 { |
|
1582 if( EColor64K == modeT && EColor64K == modeS ) |
|
1583 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelEdgeDetect, iBlendFactor, 0 ); |
|
1584 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1585 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEdgeDetect, iBlendFactor, 0 ); |
|
1586 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1587 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEdgeDetect, iBlendFactor, 0 ); |
|
1588 else |
|
1589 return KErrArgument; |
|
1590 } |
|
1591 break; |
|
1592 case EModeBlur: |
|
1593 { |
|
1594 if( EColor64K == modeT && EColor64K == modeS ) |
|
1595 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelBlur, iBlendFactor, 0 ); |
|
1596 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1597 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelBlur, iBlendFactor, 0 ); |
|
1598 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1599 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelBlur, iBlendFactor, 0 ); |
|
1600 else |
|
1601 return KErrArgument; |
|
1602 } |
|
1603 break; |
|
1604 case EModeBlurGauss: |
|
1605 { |
|
1606 if( EColor64K == modeT && EColor64K == modeS ) |
|
1607 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelBlurGauss, iBlendFactor, 0 ); |
|
1608 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1609 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelBlurGauss, iBlendFactor, 0 ); |
|
1610 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1611 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelBlurGauss, iBlendFactor, 0 ); |
|
1612 else |
|
1613 return KErrArgument; |
|
1614 } |
|
1615 break; |
|
1616 case EModeEmbossSoft: |
|
1617 { |
|
1618 if( EColor64K == modeT && EColor64K == modeS ) |
|
1619 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelEmbossSoft, iBlendFactor, 127 ); |
|
1620 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1621 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEmbossSoft, iBlendFactor, 127 ); |
|
1622 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1623 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEmbossSoft, iBlendFactor, 127 ); |
|
1624 else |
|
1625 return KErrArgument; |
|
1626 } |
|
1627 break; |
|
1628 case EModeEmbossHard: |
|
1629 { |
|
1630 if( EColor64K == modeT && EColor64K == modeS ) |
|
1631 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelEmbossHard, iBlendFactor, 127 ); |
|
1632 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1633 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEmbossHard, iBlendFactor, 127 ); |
|
1634 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1635 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEmbossHard, iBlendFactor, 127 ); |
|
1636 else |
|
1637 return KErrArgument; |
|
1638 } |
|
1639 break; |
|
1640 case EModeEnhanceDetail: |
|
1641 { |
|
1642 if( EColor64K == modeT && EColor64K == modeS ) |
|
1643 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelEnhanceDetail, iBlendFactor, 0 ); |
|
1644 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1645 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEnhanceDetail, iBlendFactor, 0 ); |
|
1646 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1647 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEnhanceDetail, iBlendFactor, 0 ); |
|
1648 else |
|
1649 return KErrArgument; |
|
1650 } |
|
1651 break; |
|
1652 case EModeEnhanceFocus: |
|
1653 { |
|
1654 if( EColor64K == modeT && EColor64K == modeS ) |
|
1655 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelEnhanceFocus, iBlendFactor, 0 ); |
|
1656 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1657 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEnhanceFocus, iBlendFactor, 0 ); |
|
1658 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1659 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEnhanceFocus, iBlendFactor, 0 ); |
|
1660 else |
|
1661 return KErrArgument; |
|
1662 } |
|
1663 break; |
|
1664 case EModeSoften: |
|
1665 { |
|
1666 if( EColor64K == modeT && EColor64K == modeS ) |
|
1667 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelSoften, iBlendFactor, 0 ); |
|
1668 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1669 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelSoften, iBlendFactor, 0 ); |
|
1670 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1671 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelSoften, iBlendFactor, 0 ); |
|
1672 else |
|
1673 return KErrArgument; |
|
1674 } |
|
1675 break; |
|
1676 case EModeSharpen: |
|
1677 { |
|
1678 if( EColor64K == modeT && EColor64K == modeS ) |
|
1679 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelSharpen, iBlendFactor, 0 ); |
|
1680 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1681 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelSharpen, iBlendFactor, 0 ); |
|
1682 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1683 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelSharpen, iBlendFactor, 0 ); |
|
1684 else |
|
1685 return KErrArgument; |
|
1686 } |
|
1687 break; |
|
1688 case EModeSharpenMore: |
|
1689 { |
|
1690 if( EColor64K == modeT && EColor64K == modeS ) |
|
1691 AknsRlEffectConvolution<TUint16,0,5,6,5>::Kernel( t, sTmp, KKernelSharpenMore, iBlendFactor, 0 ); |
|
1692 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1693 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelSharpenMore, iBlendFactor, 0 ); |
|
1694 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1695 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelSharpenMore, iBlendFactor, 0 ); |
|
1696 else |
|
1697 return KErrArgument; |
|
1698 } |
|
1699 break; |
|
1700 |
|
1701 // Convolution filter modes |
|
1702 case EModeMean: |
|
1703 { |
|
1704 if( EColor64K == modeT && EColor64K == modeS ) |
|
1705 AknsRlEffectConvolution<TUint16,0,5,6,5>::Mean( t, sTmp, iBlendFactor ); |
|
1706 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1707 AknsRlEffectConvolution<TUint32,8,8,8,8>::Mean( t, sTmp, iBlendFactor ); |
|
1708 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1709 AknsRlEffectConvolutionGray::Mean( t, sTmp, iBlendFactor ); |
|
1710 else |
|
1711 return KErrArgument; |
|
1712 } |
|
1713 break; |
|
1714 case EModeMedian: |
|
1715 { |
|
1716 if( EColor64K == modeT && EColor64K == modeS ) |
|
1717 AknsRlEffectConvolution<TUint16,0,5,6,5>::Median( t, sTmp, iBlendFactor ); |
|
1718 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1719 AknsRlEffectConvolution<TUint32,8,8,8,8>::Median( t, sTmp, iBlendFactor ); |
|
1720 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1721 AknsRlEffectConvolutionGray::Median( t, sTmp, iBlendFactor ); |
|
1722 else |
|
1723 return KErrArgument; |
|
1724 } |
|
1725 break; |
|
1726 case EModeDilate: |
|
1727 { |
|
1728 if( EColor64K == modeT && EColor64K == modeS ) |
|
1729 AknsRlEffectConvolution<TUint16,0,5,6,5>::Max( t, sTmp, iBlendFactor ); |
|
1730 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1731 AknsRlEffectConvolution<TUint32,8,8,8,8>::Max( t, sTmp, iBlendFactor ); |
|
1732 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1733 AknsRlEffectConvolutionGray::Max( t, sTmp, iBlendFactor ); |
|
1734 else |
|
1735 return KErrArgument; |
|
1736 } |
|
1737 break; |
|
1738 case EModeErode: |
|
1739 { |
|
1740 if( EColor64K == modeT && EColor64K == modeS ) |
|
1741 AknsRlEffectConvolution<TUint16,0,5,6,5>::Min( t, sTmp, iBlendFactor ); |
|
1742 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1743 AknsRlEffectConvolution<TUint32,8,8,8,8>::Min( t, sTmp, iBlendFactor ); |
|
1744 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1745 AknsRlEffectConvolutionGray::Min( t, sTmp, iBlendFactor ); |
|
1746 else |
|
1747 return KErrArgument; |
|
1748 } |
|
1749 break; |
|
1750 |
|
1751 default: |
|
1752 return KErrArgument; |
|
1753 } |
|
1754 #else // ASM versions for hardware |
|
1755 switch( TMode( iMode ) ) |
|
1756 { |
|
1757 // Convolution kernel modes |
|
1758 case EModeEdge: |
|
1759 { |
|
1760 if( EColor64K == modeT && EColor64K == modeS ) |
|
1761 AConvolute64KEdge( t, sTmp, iBlendFactor ); |
|
1762 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1763 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEdgeDetect, iBlendFactor, 0 ); |
|
1764 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1765 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEdgeDetect, iBlendFactor, 0 ); |
|
1766 else |
|
1767 return KErrArgument; |
|
1768 } |
|
1769 break; |
|
1770 case EModeBlur: |
|
1771 { |
|
1772 if( EColor64K == modeT && EColor64K == modeS ) |
|
1773 AConvolute64KBlur( t, sTmp, iBlendFactor ); |
|
1774 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1775 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelBlur, iBlendFactor, 0 ); |
|
1776 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1777 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelBlur, iBlendFactor, 0 ); |
|
1778 else |
|
1779 return KErrArgument; |
|
1780 } |
|
1781 break; |
|
1782 case EModeBlurGauss: |
|
1783 { |
|
1784 if( EColor64K == modeT && EColor64K == modeS ) |
|
1785 AConvolute64KBlurGauss( t, sTmp, iBlendFactor ); |
|
1786 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1787 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelBlurGauss, iBlendFactor, 0 ); |
|
1788 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1789 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelBlurGauss, iBlendFactor, 0 ); |
|
1790 else |
|
1791 return KErrArgument; |
|
1792 } |
|
1793 break; |
|
1794 case EModeEmbossSoft: |
|
1795 { |
|
1796 if( EColor64K == modeT && EColor64K == modeS ) |
|
1797 AConvolute64KEmbossSoft( t, sTmp, iBlendFactor ); |
|
1798 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1799 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEmbossSoft, iBlendFactor, 127 ); |
|
1800 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1801 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEmbossSoft, iBlendFactor, 127 ); |
|
1802 else |
|
1803 return KErrArgument; |
|
1804 } |
|
1805 break; |
|
1806 case EModeEmbossHard: |
|
1807 { |
|
1808 if( EColor64K == modeT && EColor64K == modeS ) |
|
1809 AConvolute64KEmbossHard( t, sTmp, iBlendFactor ); |
|
1810 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1811 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEmbossHard, iBlendFactor, 127 ); |
|
1812 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1813 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEmbossHard, iBlendFactor, 127 ); |
|
1814 else |
|
1815 return KErrArgument; |
|
1816 } |
|
1817 break; |
|
1818 case EModeEnhanceDetail: |
|
1819 { |
|
1820 if( EColor64K == modeT && EColor64K == modeS ) |
|
1821 AConvolute64KEnhanceDetail( t, sTmp, iBlendFactor ); |
|
1822 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1823 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEnhanceDetail, iBlendFactor, 0 ); |
|
1824 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1825 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEnhanceDetail, iBlendFactor, 0 ); |
|
1826 else |
|
1827 return KErrArgument; |
|
1828 } |
|
1829 break; |
|
1830 case EModeEnhanceFocus: |
|
1831 { |
|
1832 if( EColor64K == modeT && EColor64K == modeS ) |
|
1833 AConvolute64KEnhanceFocus( t, sTmp, iBlendFactor ); |
|
1834 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1835 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelEnhanceFocus, iBlendFactor, 0 ); |
|
1836 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1837 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelEnhanceFocus, iBlendFactor, 0 ); |
|
1838 else |
|
1839 return KErrArgument; |
|
1840 } |
|
1841 break; |
|
1842 case EModeSoften: |
|
1843 { |
|
1844 if( EColor64K == modeT && EColor64K == modeS ) |
|
1845 AConvolute64KSoften( t, sTmp, iBlendFactor ); |
|
1846 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1847 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelSoften, iBlendFactor, 0 ); |
|
1848 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1849 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelSoften, iBlendFactor, 0 ); |
|
1850 else |
|
1851 return KErrArgument; |
|
1852 } |
|
1853 break; |
|
1854 case EModeSharpen: |
|
1855 { |
|
1856 if( EColor64K == modeT && EColor64K == modeS ) |
|
1857 AConvolute64KSharpen( t, sTmp, iBlendFactor ); |
|
1858 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1859 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelSharpen, iBlendFactor, 0 ); |
|
1860 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1861 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelSharpen, iBlendFactor, 0 ); |
|
1862 else |
|
1863 return KErrArgument; |
|
1864 } |
|
1865 break; |
|
1866 case EModeSharpenMore: |
|
1867 { |
|
1868 if( EColor64K == modeT && EColor64K == modeS ) |
|
1869 AConvolute64KSharpenMore( t, sTmp, iBlendFactor ); |
|
1870 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1871 AknsRlEffectConvolution<TUint32,8,8,8,8>::Kernel( t, sTmp, KKernelSharpenMore, iBlendFactor, 0 ); |
|
1872 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1873 AknsRlEffectConvolutionGray::Kernel( t, sTmp, KKernelSharpenMore, iBlendFactor, 0 ); |
|
1874 else |
|
1875 return KErrArgument; |
|
1876 } |
|
1877 break; |
|
1878 |
|
1879 // Convolution filter modes |
|
1880 case EModeMean: |
|
1881 { |
|
1882 if( EColor64K == modeT && EColor64K == modeS ) |
|
1883 AknsRlEffectConvolution<TUint16,0,5,6,5>::Mean( t, sTmp, iBlendFactor ); |
|
1884 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1885 AknsRlEffectConvolution<TUint32,8,8,8,8>::Mean( t, sTmp, iBlendFactor ); |
|
1886 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1887 AknsRlEffectConvolutionGray::Mean( t, sTmp, iBlendFactor ); |
|
1888 else |
|
1889 return KErrArgument; |
|
1890 } |
|
1891 break; |
|
1892 case EModeMedian: |
|
1893 { |
|
1894 if( EColor64K == modeT && EColor64K == modeS ) |
|
1895 AknsRlEffectConvolution<TUint16,0,5,6,5>::Median( t, sTmp, iBlendFactor ); |
|
1896 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1897 AknsRlEffectConvolution<TUint32,8,8,8,8>::Median( t, sTmp, iBlendFactor ); |
|
1898 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1899 AknsRlEffectConvolutionGray::Median( t, sTmp, iBlendFactor ); |
|
1900 else |
|
1901 return KErrArgument; |
|
1902 } |
|
1903 break; |
|
1904 case EModeDilate: |
|
1905 { |
|
1906 if( EColor64K == modeT && EColor64K == modeS ) |
|
1907 AknsRlEffectConvolution<TUint16,0,5,6,5>::Max( t, sTmp, iBlendFactor ); |
|
1908 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1909 AknsRlEffectConvolution<TUint32,8,8,8,8>::Max( t, sTmp, iBlendFactor ); |
|
1910 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1911 AknsRlEffectConvolutionGray::Max( t, sTmp, iBlendFactor ); |
|
1912 else |
|
1913 return KErrArgument; |
|
1914 } |
|
1915 break; |
|
1916 case EModeErode: |
|
1917 { |
|
1918 if( EColor64K == modeT && EColor64K == modeS ) |
|
1919 AknsRlEffectConvolution<TUint16,0,5,6,5>::Min( t, sTmp, iBlendFactor ); |
|
1920 else if( EColor16MU == modeT && EColor16MU == modeS ) |
|
1921 AknsRlEffectConvolution<TUint32,8,8,8,8>::Min( t, sTmp, iBlendFactor ); |
|
1922 else if( EGray256 == modeT && EGray256 == modeS ) |
|
1923 AknsRlEffectConvolutionGray::Min( t, sTmp, iBlendFactor ); |
|
1924 else |
|
1925 return KErrArgument; |
|
1926 } |
|
1927 break; |
|
1928 |
|
1929 default: |
|
1930 return KErrArgument; |
|
1931 } |
|
1932 |
|
1933 #endif // !__MARM_ARMI__ |
|
1934 |
|
1935 delete sNew; |
|
1936 } |
|
1937 else |
|
1938 { |
|
1939 // Required layers were not provided |
|
1940 return KErrArgument; |
|
1941 } |
|
1942 |
|
1943 return KErrNone; |
|
1944 } |
|
1945 |
|
1946 /*lint -restore */ |
|
1947 |
|
1948 // End of File |