javauis/lcdui_akn/lcdui/src/CMIDScaler.cpp
branchRCL_3
changeset 19 04becd199f91
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2009 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:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <e32cmn.h>
       
    19 #include <j2me/jdebug.h>
       
    20 
       
    21 #include "CMIDScaler.h"
       
    22 
       
    23 #define REL_MODE
       
    24 
       
    25 #ifdef REL_MODE
       
    26 #include "CMIDMenuHandler.h" // For TlsStruct
       
    27 #else
       
    28 struct TlsStruct
       
    29 {
       
    30     CMIDScaler* iScaler;
       
    31 };
       
    32 
       
    33 TlsStruct* tls = NULL;
       
    34 #endif
       
    35 
       
    36 /*
       
    37  * Internal definitions.
       
    38  */
       
    39 #define INT_PRECISION 12 // !Max 12!
       
    40 #define INT_FULL_PXL (1<<INT_PRECISION)
       
    41 #define INT_HALF_PXL (1<<(INT_PRECISION-1))
       
    42 
       
    43 /*
       
    44  * Internal macros.
       
    45  */
       
    46 #define SET_SWI_BIT(x) ((x) | 0x8000)
       
    47 #define CLR_SWI_BIT(x) ((x) & 0x7fff)
       
    48 #define TST_SWI_BIT(x) (((x) & 0x8000) != 0)
       
    49 
       
    50 #if !defined (__WINS__) && !defined (__WINSCW__)
       
    51 #define ARMV5_OPTIMIZATIONS
       
    52 #endif
       
    53 
       
    54 
       
    55 #if defined(ARMV5_OPTIMIZATIONS)
       
    56 void InterpolateOne2Four_kernel(const TUint32* in,
       
    57                                 TUint32* out,
       
    58                                 TUint32 width,
       
    59                                 TUint32 height,
       
    60                                 TUint32 offset);
       
    61 #endif
       
    62 // ---------------------------------------------------------------------------
       
    63 //
       
    64 // ---------------------------------------------------------------------------
       
    65 //
       
    66 CMIDScaler* CMIDScaler::NewL()
       
    67 {
       
    68     // For Some reason codescanner sets error "error: leave: high: canpanic:
       
    69     // leaving function called in non-leaving function" even though this is
       
    70     // a leaving function!
       
    71 
       
    72     CMIDScaler* sca = new(ELeave) CMIDScaler();  // codescanner::leave
       
    73     CleanupStack::PushL(sca);   // codescanner::leave
       
    74     sca->ConstructL(); // codescanner::leave
       
    75     CleanupStack::Pop(sca);
       
    76     return sca;
       
    77 }
       
    78 
       
    79 // ---------------------------------------------------------------------------
       
    80 // To delete this object.
       
    81 //
       
    82 // @Preconditions The following conditions must be true prior the calling this
       
    83 // method; otherwise, its operation is undefined.
       
    84 // - None
       
    85 //
       
    86 // @Postconditions The following conditions are true immediately after
       
    87 // returning from this method, if the bitmap is processed.
       
    88 // - None
       
    89 //
       
    90 // @param None.
       
    91 // @return None.
       
    92 // @exception None.
       
    93 //
       
    94 // ---------------------------------------------------------------------------
       
    95 //
       
    96 CMIDScaler::~CMIDScaler()
       
    97 {
       
    98     iLock.Close();
       
    99     delete iBmap;
       
   100 }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 // To interpolate an input image.
       
   104 //
       
   105 // @Definition This method interpolates the input bitmap. It returns the
       
   106 // reference to the interpolated bitmap or NULL, if it is not able to
       
   107 // process the input bitmap for some reason. The ownership of the output
       
   108 // bitmap is not change.
       
   109 //
       
   110 // This method is synchronized.
       
   111 //
       
   112 // @Preconditions The following conditions must be true prior the calling this
       
   113 // method; otherwise, its operation is undefined.
       
   114 // - None
       
   115 //
       
   116 // @Postconditions The following conditions are true immediately after
       
   117 // returning from this method, if the bitmap is processed.
       
   118 // - aImgIn is untouched.
       
   119 // - iBmap.size == outWidth*outHeight.
       
   120 // - iBmap.mode == aMode.
       
   121 //
       
   122 // @param aMode - A display mode.
       
   123 // @param aImgIn - A pointer to the input image.
       
   124 // @param aWidth - A width of an input image.
       
   125 // @param aHeight - A height of an input image.
       
   126 // @param aOffset - A offset of an input image: line = offset + width.
       
   127 // @param aOutWidth - A width of an output image.
       
   128 // @param aOutWeight - A height of an output image.
       
   129 // @return Reference to the interpolated bitmap, or NULL.
       
   130 // @exception None.
       
   131 //
       
   132 // ---------------------------------------------------------------------------
       
   133 //
       
   134 CFbsBitmap* CMIDScaler::Process(TDisplayMode aMode,
       
   135                                 const TUint32* aImgIn,
       
   136                                 TUint aWidth,
       
   137                                 TUint aHeight,
       
   138                                 TUint aOffset,
       
   139                                 TUint aOutWidth,
       
   140                                 TUint aOutHeight)
       
   141 {
       
   142     // Debug macros.
       
   143     //__UHEAP_MARK;
       
   144 
       
   145     DEBUG_INT("CMIDScaler::Process - mod: %d", aMode);
       
   146     DEBUG_INT("CMIDScaler::Process - wid: %d", aWidth);
       
   147     DEBUG_INT("CMIDScaler::Process - hei: %d", aHeight);
       
   148     DEBUG_INT("CMIDScaler::Process - off: %d", aOffset);
       
   149     DEBUG_INT("CMIDScaler::Process - owi: %d", aOutWidth);
       
   150     DEBUG_INT("CMIDScaler::Process - ohe: %d", aOutHeight);
       
   151     DEBUG_INT("CMIDScaler::Process - maX: %d", iMaxX);
       
   152     DEBUG_INT("CMIDScaler::Process - maY: %d", iMaxY);
       
   153     DEBUG_INT("CMIDScaler::Process - inX: %d", iIntX);
       
   154     DEBUG_INT("CMIDScaler::Process - inY: %d", iIntY);
       
   155 
       
   156     CFbsBitmap* bmap = NULL;
       
   157 
       
   158     // Wait for the access to the lock object.
       
   159     iLock.Wait();
       
   160 
       
   161     if ((aMode == EColor16MU || aMode == EColor16MA) &&
       
   162             aWidth >= 2 &&
       
   163             aWidth <= aOutWidth &&
       
   164             aWidth <= iMaxX &&
       
   165             aHeight >= 2 &&
       
   166             aHeight <= aOutHeight &&
       
   167             aHeight <= iMaxY &&
       
   168             aOutWidth <= iIntX &&
       
   169             aOutHeight <= iIntY)
       
   170     {
       
   171         TInt err = KErrNone;
       
   172 
       
   173         // If this is the first call of this method, create new bitmap.
       
   174         if (iIsBm == EFalse)
       
   175         {
       
   176             iBmap = new CFbsBitmap;
       
   177             if (iBmap)
       
   178             {
       
   179                 err = iBmap->Create(TSize(aOutWidth, aOutHeight), aMode);
       
   180                 if (err != KErrNone)
       
   181                 {
       
   182                     delete iBmap;
       
   183                     iBmap = NULL;
       
   184                 }
       
   185                 else
       
   186                 {
       
   187                     iIsBm = ETrue;
       
   188                 }
       
   189             }
       
   190         }
       
   191 
       
   192         // Do interpolation.
       
   193         if (iIsBm)
       
   194         {
       
   195             if (aOutWidth == 2*aWidth && aOutHeight == 2*aHeight)
       
   196             {
       
   197                 InterpolateOne2Four(aImgIn, aWidth, aHeight, aOffset, aMode);
       
   198             }
       
   199             else
       
   200             {
       
   201                 Interpolate(aImgIn, aWidth, aHeight, aOffset, aOutWidth, aOutHeight, aMode);
       
   202             }
       
   203             bmap = iBmap;
       
   204         }
       
   205     }
       
   206 
       
   207     // Release the lock object.
       
   208     iLock.Signal();
       
   209 
       
   210     // Debug macros.
       
   211     //__UHEAP_MARKEND;
       
   212 
       
   213     return bmap;
       
   214 }
       
   215 
       
   216 // ---------------------------------------------------------------------------
       
   217 // To do 1st phase construction for this object.
       
   218 //
       
   219 // @Preconditions The following conditions must be true prior the calling this
       
   220 // method; otherwise, its operation is undefined.
       
   221 // - None
       
   222 //
       
   223 // @Postconditions The following conditions are true immediately after
       
   224 // returning from this method, if the bitmap is processed.
       
   225 // - None
       
   226 //
       
   227 // @param None.
       
   228 // @return None.
       
   229 // @exception None.
       
   230 //
       
   231 // ---------------------------------------------------------------------------
       
   232 //
       
   233 CMIDScaler::CMIDScaler()
       
   234 {
       
   235     iBpp  = 4;
       
   236     iRefC = 0;
       
   237     iMode = EColor16MU;
       
   238     iMaxX = iIntX = 640;
       
   239     iMaxY = iIntY = 640;
       
   240     iIsBm = EFalse;
       
   241     iLock.CreateLocal();
       
   242 }
       
   243 
       
   244 // ---------------------------------------------------------------------------
       
   245 // To do 2nd phase construction for this object.
       
   246 //
       
   247 // @Preconditions The following conditions must be true prior the calling this
       
   248 // method; otherwise, its operation is undefined.
       
   249 // - None
       
   250 //
       
   251 // @Postconditions The following conditions are true immediately after
       
   252 // returning from this method, if the bitmap is processed.
       
   253 // - None
       
   254 //
       
   255 // @param None.
       
   256 // @return None.
       
   257 // @exception If the method is not able to allocate necessary buffers.
       
   258 //
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CMIDScaler::ConstructL()
       
   262 {
       
   263 }
       
   264 
       
   265 
       
   266 // ---------------------------------------------------------------------------
       
   267 // To do differential interpolation for an input image.
       
   268 //
       
   269 // @Definition The differential interpolation is based on the equation
       
   270 //
       
   271 //    o = | a, if l = dist(o,a)
       
   272 //        | b, if l = dist(o,b)
       
   273 //        | c, if l = dist(o,c)
       
   274 //        | d, if l = dist(o,d)
       
   275 //
       
   276 // where o is an output pixel,
       
   277 //
       
   278 //    l = min(dist(o,a), dist(o,b), dist(o,c), dist(o,d))
       
   279 //
       
   280 // and dist is a component metric, i.e., dist(x,y) = |x1-y1| + |x2-y2|.
       
   281 //
       
   282 // Lets assume that we have to interpolate one output pixel o. It has always
       
   283 // four surrounding input pixels orientated as depicted in Figure 1:
       
   284 //
       
   285 //    a<------x>+<------->b
       
   286 //     |      : :        |
       
   287 //     |      : :        |
       
   288 //     |   A1 : :   A2   |
       
   289 //     |      : :        |
       
   290 //     |      : :        |
       
   291 //     +------:-+--------+
       
   292 //     |      : :        |
       
   293 //     y......o :        |
       
   294 //     |   A3   :   A4   |
       
   295 //     |        :        |
       
   296 //     |        :        |
       
   297 //    c<------->+<------->d
       
   298 //
       
   299 // Figure 1. An output pixel o is always surrounded by four input pixels, a, b,
       
   300 //           c and d. All pixels in specific area will have same value, e.g.,
       
   301 //           pixel o in area A3 will have same value as c.
       
   302 //
       
   303 // It is obvious that c is the nearest pixel to o in Figure 1. Therefore o will
       
   304 // have value of c.
       
   305 //
       
   306 // The basic problem of interpolation is how the last pixels are interpolated.
       
   307 // Here the last row and column are replicated (look Figure 2), so the last
       
   308 // pixels are interpolated same way as the others.
       
   309 //
       
   310 // :    :    :  :  :    :    :    :
       
   311 // +----+----+ ... +----+----+.....
       
   312 // | v0 | v1 | ... |vN-2|vN-1|vN-1:
       
   313 // +----+----+ ... +----+----+.....
       
   314 // : v0 : v1 : ... :vN-2:vN-1:vN-1:<- Last pseudo row
       
   315 // ........... ... ................
       
   316 //                              |
       
   317 //                              +- Last pseudo column
       
   318 //
       
   319 // Figure 2. Pseudo pixels are added in order to get simple implementation.
       
   320 //
       
   321 // @Preconditions The following conditions must be true prior the calling this
       
   322 // method; otherwise, its operation is undefined.
       
   323 // - 2 <= width <= maxX
       
   324 // - 2 <= height
       
   325 // - width <= outWidth
       
   326 // - height <= outHeight
       
   327 // - outWidth <= intX
       
   328 // - outHeight <= intY
       
   329 // - log2(INT_FULL_PXL*width) <= 32
       
   330 // - log2(INT_FULL_PXL*height) <= 32
       
   331 // - aMode == EColor16MU || EColor16MA
       
   332 // - IsCompressedInRAM == EFalse
       
   333 //
       
   334 // @Postconditions The following conditions are true immediately after
       
   335 // returning from this method.
       
   336 // - iBmap.size == outWidth*outHeight.
       
   337 // - iBmap.mode == aMode.
       
   338 //
       
   339 // @param imgIn - A pointer to the input image.
       
   340 // @param width - A width of an input image.
       
   341 // @param height - A height of an input image.
       
   342 // @param offset - A offset of an input image: line = offset + width.
       
   343 // @param outWidth - A width of an output image.
       
   344 // @param outWeight - A height of an output image.
       
   345 // @param aMode - A display mode.
       
   346 // @return None.
       
   347 // @exception None.
       
   348 //
       
   349 // @Note This method has originally been a bilinear interpolation. Hence the
       
   350 // element of the weight tables has 16 bits, but here only two of them are
       
   351 // used.
       
   352 //
       
   353 // ---------------------------------------------------------------------------
       
   354 //
       
   355 void CMIDScaler::Interpolate(const TUint32* aImgIn,
       
   356                              TUint width,
       
   357                              TUint height,
       
   358                              TUint offset,
       
   359                              TUint outWidth,
       
   360                              TUint outHeight,
       
   361                              TDisplayMode aMode)
       
   362 {
       
   363 
       
   364     TUint32 stepX, stepY, roundX, roundY, j, k;
       
   365     const TUint32 *src;
       
   366     TUint32 *dst;
       
   367 
       
   368 
       
   369     if (aMode != iBmap->DisplayMode())
       
   370         iBmap->SetDisplayMode(aMode);
       
   371     if ((iBmap->SizeInPixels().iWidth != outWidth)
       
   372             || (iBmap->SizeInPixels().iHeight != outHeight))
       
   373         iBmap->Resize(TSize(outWidth, outHeight));
       
   374 
       
   375     stepX = (TUint32)((16384*width)/outWidth);
       
   376     stepY = (TUint32)((16384*height)/outHeight);
       
   377     roundX = stepX>>1;
       
   378     roundY = stepY>>1;
       
   379     iBmap->LockHeap();
       
   380     dst = iBmap->DataAddress();
       
   381 
       
   382     for (j = 0; j < outHeight; j++)
       
   383     {
       
   384         // Interpolate one scanline.
       
   385         src = &aImgIn[(width+offset)*((stepY*j + roundY)>>14)];
       
   386         for (k = roundX; k < outWidth*stepX + roundX; k+=stepX)
       
   387         {
       
   388             *dst++ = src[k>>14];
       
   389         }
       
   390     }
       
   391     iBmap->UnlockHeap();
       
   392 
       
   393 }
       
   394 
       
   395 // ---------------------------------------------------------------------------
       
   396 // To double scale the bitmap.
       
   397 //
       
   398 // @Preconditions The following conditions must be true prior to calling
       
   399 // this method; otherwise, its operation is undefined.
       
   400 // - width(src) > 0
       
   401 // - height(src) > 0
       
   402 // - width(dst) == 2*width(src)
       
   403 // - height(dst) == 2*height(src)
       
   404 // - IsCompressedInRAM == EFalse
       
   405 // - DisplayMode() == EColor16MU || EColor16MA
       
   406 //
       
   407 // @Postconditions The following condition is true immediately after
       
   408 // returning from this method.
       
   409 // - iBmap.size == outWidth*outHeight.
       
   410 // - iBmap.mode == aMode.
       
   411 //
       
   412 // @param aImgIn - A pointer to the input image.
       
   413 // @param aWidth - A width of an input image.
       
   414 // @param aHeight - A height of an input image.
       
   415 // @param aOffset - A offset of an input image: line = offset + width.
       
   416 // @param aMode - A display mode.
       
   417 // @return None.
       
   418 // @exception None.
       
   419 // ---------------------------------------------------------------------------
       
   420 //
       
   421 void CMIDScaler::InterpolateOne2Four(const TUint32* aImgIn,
       
   422                                      TUint aWidth,
       
   423                                      TUint aHeight,
       
   424                                      TUint aOffset,
       
   425                                      TDisplayMode aMode)
       
   426 {
       
   427     if (aMode != iBmap->DisplayMode())
       
   428         iBmap->SetDisplayMode(aMode);
       
   429     if ((iBmap->SizeInPixels().iWidth != 2*aWidth)
       
   430             || (iBmap->SizeInPixels().iHeight != 2*aHeight))
       
   431         iBmap->Resize(TSize(2*aWidth, 2*aHeight));
       
   432 
       
   433     iBmap->LockHeap();
       
   434     TUint32* tmp1 = iBmap->DataAddress();
       
   435 
       
   436     // Do double scaling.
       
   437 #if defined(ARMV5_OPTIMIZATIONS)
       
   438     InterpolateOne2Four_kernel(aImgIn, tmp1, aWidth, aHeight, aOffset);
       
   439 #else
       
   440     // Initialize variables.
       
   441     TInt32 x = 0;
       
   442     TInt32 y = 0;
       
   443     TInt32 i = 0;
       
   444     TUint32 pxl = 0;
       
   445     const TUint32* src1 = NULL;
       
   446     TUint32* dst1 = NULL;
       
   447     TUint32* dst2 = NULL;
       
   448 
       
   449     for (y = 0; y < aHeight; y++)
       
   450     {
       
   451         i = (aWidth + aOffset)*y;
       
   452 
       
   453         src1 = aImgIn;
       
   454         dst1 = dst2 = tmp1;
       
   455         src1 = &src1[i];
       
   456         dst1 = &dst1[2*aWidth*2*y];
       
   457         dst2 = &dst2[2*aWidth*(2*y+1)];
       
   458 
       
   459         // Copy one scanline.
       
   460         for (x = 0; x < aWidth; x++)
       
   461         {
       
   462             pxl = *src1++;
       
   463             *dst1++ = pxl;
       
   464             *dst1++ = pxl;
       
   465             *dst2++ = pxl;
       
   466             *dst2++ = pxl;
       
   467         }
       
   468     }
       
   469 #endif
       
   470     iBmap->UnlockHeap();
       
   471 
       
   472 }
       
   473 
       
   474 
       
   475 #if defined(ARMV5_OPTIMIZATIONS)
       
   476 __asm void InterpolateOne2Four_kernel(const TUint32* in,
       
   477                                       TUint32* out,
       
   478                                       TUint32 width,
       
   479                                       TUint32 height,
       
   480                                       TUint32 offset)
       
   481 {
       
   482 // r0 = in
       
   483 // r1 = out
       
   484 // r2 = width
       
   485 // r3 = height
       
   486 // sp[0] = offset
       
   487 
       
   488     CODE32
       
   489 
       
   490     CMP     r2, #0
       
   491     BXEQ    lr
       
   492     CMP     r3, #0
       
   493     BXEQ    lr
       
   494 
       
   495     STMFD   sp!, {r4-r12, lr}
       
   496 
       
   497     MOV     r12, r2                 // width
       
   498     ADD     r14, r1, r2, LSL #3     // &out[2*width]
       
   499 
       
   500 CMIDScaler_InterpolateOne2Four_kernel_outerLoop
       
   501         MOVS    r2, r12, ASR #2         // width/4 = number of 4x32 bit reads
       
   502 
       
   503 CMIDScaler_InterpolateOne2Four_kernel_innerLoop
       
   504 // read the 4x32bit-aligned input and interpolate
       
   505     LDMIANE r0!, {r4, r6, r8, r10}
       
   506     MOVNE   r5, r4
       
   507     MOVNE   r7, r6
       
   508     MOVNE   r9, r8
       
   509     MOVNE   r11, r10
       
   510     STMIANE r1!, {r4-r11}
       
   511     STMIANE r14!, {r4-r11}
       
   512     SUBSNE  r2, #1
       
   513     BNE     CMIDScaler_InterpolateOne2Four_kernel_innerLoop
       
   514 
       
   515     MOV     r2, r12, ASR #2
       
   516     SUBS    r2, r12, r2, LSL #2     // number of unaligned 32-bit reads
       
   517 
       
   518 // read the unaligned tail and interpolate
       
   519 CMIDScaler_InterpolateOne2Four_kernel_tailLoop
       
   520 
       
   521     LDRNE   r6, [r0], #4
       
   522     STRNE   r6, [r1], #4
       
   523     STRNE   r6, [r1], #4
       
   524     STRNE   r6, [r14], #4
       
   525     STRNE   r6, [r14], #4
       
   526     SUBSNE  r2, #1
       
   527     BNE     CMIDScaler_InterpolateOne2Four_kernel_tailLoop
       
   528 
       
   529 // update pointers to the next line
       
   530     LDR     r4, [sp, #(10*4)]
       
   531     SUBS    r3, #1
       
   532     MOV     r1, r14
       
   533     ADD     r14, r1, r12, LSL #3
       
   534     ADD     r0, r0, r4, LSL #2
       
   535     BNE     CMIDScaler_InterpolateOne2Four_kernel_outerLoop
       
   536 
       
   537     LDMFD   sp!, {r4-r12, lr}
       
   538     BX      lr
       
   539 }
       
   540 #endif