skins/AknSkins/rlpluginsrc/AknsRlEffectPluginConvolution.cpp
changeset 0 05e9090e2422
equal deleted inserted replaced
-1:000000000000 0:05e9090e2422
       
     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