void AConvolute64KBlurGauss( CFbsBitmap& aTarget,
                             const CFbsBitmap& aSource,
                             const TInt aBlendFactor )
    {
    TInt width  = aTarget.SizeInPixels().iWidth;
    TInt height = aTarget.SizeInPixels().iHeight;

    // CFbsBitmap::ScanLineLength returns bytes 
    TInt targetScanW  = CFbsBitmap::ScanLineLength(
                                aTarget.SizeInPixels().iWidth,
                                aTarget.DisplayMode());
    TInt sourceScanW  = CFbsBitmap::ScanLineLength(
                                aSource.SizeInPixels().iWidth,
                                aSource.DisplayMode());

    TInt combinedScanW = (targetScanW << 16) + sourceScanW;

    // Prepare the data addresses
    aTarget.LockHeap( ETrue ); // Lock the global bitmap heap
    TUint* targetAddr = reinterpret_cast<TUint*>( aTarget.DataAddress() );
    TUint* sourceAddr = reinterpret_cast<TUint*>( aSource.DataAddress() );

    ADoConvolute64KBlurGauss(targetAddr, sourceAddr, combinedScanW, width, height, aBlendFactor);

    aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap
    }
    //------------------------------------------------------------------------
    static void ProcessRgbToRgb( const CFbsBitmap& aTarget,
                                 const CFbsBitmap& aSource,
                                 const TInt aTreshold,
                                 const TInt aBlendFactor )
        {
        // ScanLineLength returns bytes, but width must match the Type
        TInt width  = CFbsBitmap::ScanLineLength( aSource.SizeInPixels().iWidth,
                                                  aSource.DisplayMode() ) / sizeof(Type);
        TInt height = aSource.SizeInPixels().iHeight;

        TInt pixelCount = width * height;
        TInt shade;
        TInt r,g,b;

        aTarget.LockHeap( ETrue ); // Lock the global bitmap heap
        Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() );
        Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() );

        for( TInt index = 0; index < pixelCount; ++index )
            {
            r = AknsRlRgb<Type,X,R,G,B>::R8(*dataS);
            g = AknsRlRgb<Type,X,R,G,B>::G8(*dataS);
            b = AknsRlRgb<Type,X,R,G,B>::B8(*dataS);

            // Pixel intensity = grayscale value
            shade = AknsRlUtil::Grayscale( TUint8(r), TUint8(g), TUint8(b) );

            // Convert to B&W
            if( shade < aTreshold )
                shade = 0;
            else
                shade = 255;

            // Exposure blending
            // Note: It is assumed that arithmetic shifting is supported
            // -> negative values are shifted correctly
            r = (shade * aBlendFactor + (255 - aBlendFactor) * r) >> 8;
            g = (shade * aBlendFactor + (255 - aBlendFactor) * g) >> 8;
            b = (shade * aBlendFactor + (255 - aBlendFactor) * b) >> 8;

            if( r < 0 ) r = 0; else if( r > 255 ) r = 255;
            if( g < 0 ) g = 0; else if( g > 255 ) g = 255;
            if( b < 0 ) b = 0; else if( b > 255 ) b = 255;

            AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(r), TUint8(g), TUint8(b) );

            dataT++;
            dataS++;
            }

        aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap
        }
    //------------------------------------------------------------------------
    static void ProcessRgbToGray( const CFbsBitmap& aTarget,
                                  const CFbsBitmap& aSource,
                                  const TInt aTreshold )
        {
        TInt width  = aSource.SizeInPixels().iWidth;
        TInt height = aSource.SizeInPixels().iHeight;

        // ScanLineLength returns bytes, but width must match the Type
        TInt scanT = CFbsBitmap::ScanLineLength(width, aTarget.DisplayMode());
        TInt scanS = CFbsBitmap::ScanLineLength(width, aSource.DisplayMode()) / sizeof(Type);

        TInt shade;

        TInt pitchT = scanT - width;
        TInt pitchS = scanS - width;

        aTarget.LockHeap( ETrue ); // Lock the global bitmap heap
        TUint8* dataT = reinterpret_cast<TUint8*>( aTarget.DataAddress() );
        Type* dataS = reinterpret_cast<Type*>( aSource.DataAddress() );

        TInt x, y;
        for( y=0; y < height; y++ )
            {
            for( x=0; x < width; x++ )
                {
                // Pixel intensity = grayscale value
                shade = AknsRlUtil::Grayscale( AknsRlRgb<Type,X,R,G,B>::R8(*dataS),
                                               AknsRlRgb<Type,X,R,G,B>::G8(*dataS),
                                               AknsRlRgb<Type,X,R,G,B>::B8(*dataS) );

                // Convert to B&W
                if( shade < aTreshold )
                    *dataT = 0;
                else
                    *dataT = 255;

                dataT++;
                dataS++;
                }

            dataT = dataT + pitchT;
            dataS = dataS + pitchS;
            }

        aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap
        }
    //------------------------------------------------------------------------
    static void ProcessGrayToRgb( const CFbsBitmap& aTarget,
                                  const CFbsBitmap& aSource,
                                  const TInt aTreshold )
        {
        TInt width  = aSource.SizeInPixels().iWidth;
        TInt height = aSource.SizeInPixels().iHeight;

        // ScanLineLength returns bytes, but width must match the Type
        TInt scanT = CFbsBitmap::ScanLineLength(width, aTarget.DisplayMode()) / sizeof(Type);
        TInt scanS = CFbsBitmap::ScanLineLength(width, aSource.DisplayMode());

        TInt pitchT = scanT - width;
        TInt pitchS = scanS - width;

        aTarget.LockHeap( ETrue ); // Lock the global bitmap heap
        Type* dataT = reinterpret_cast<Type*>( aTarget.DataAddress() );
        TUint8* dataS = reinterpret_cast<TUint8*>( aSource.DataAddress() );

        TInt x, y;
        for( y=0; y < height; y++ )
            {
            for( x=0; x < width; x++ )
                {
                // Convert to B&W
                if( *dataS < aTreshold )
                    AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(0), TUint8(0), TUint8(0) );
                else
                    AknsRlRgb<Type,X,R,G,B>::SetRgb8( dataT, TUint8(255), TUint8(255), TUint8(255) );

                dataT++;
                dataS++;
                }

            dataT = dataT + pitchT;
            dataS = dataS + pitchS;
            }

        aTarget.UnlockHeap( ETrue ); // Unlock the global bitmap heap
        }
void S60ImageUtil::calculateVisibleRect(Image* aImage)
{
   if (aImage->iHasMask) {
      CFbsBitmap* mask = aImage->GetMask();
      TInt xmin = aImage->iWidth;
      TInt xmax = 0;
      TInt ymin = aImage->iHeight;
      TInt ymax = 0;
#if defined USE_AKN_LIB
      //Iterating the pixels with GetPixel() works for sure on all symbian,
      //but it's pretty slow and we have to look at every one pixel.
      //On a 800 x 800 image we do 640 000 GetPixel() iterations.
      TRgb color;
      TRgb white(255, 255, 255);
      for (TInt y = 0; y < aImage->iHeight; y++) {
         for (TInt x = 0; x < aImage->iWidth; x++) {
            mask->GetPixel(color, TPoint(x, y));
            if (color == white) {
               if (xmin > x) {
                  xmin = x;
               }
               if (xmax < x) {
                  xmax = x;
               }
               if (ymin > y) {
                  ymin = y;
               }
               if (ymax < y) {
                  ymax = y;
               }
            }
         }
      }
#else
      //Iterating the pixels by hand in memory probably works on all symbian,
      //it's much faster since we look at 8 pixels at a time, 
      //It needs some testing and verification.
      //On a 800 x 800 image we do roughly 83 000 iterations.
      TDisplayMode dMode = mask->DisplayMode();
      if (dMode == EGray2) {
# ifndef NAV2_CLIENT_SERIES60_V1
         mask->LockHeap();
# endif
         TUint32* imgPtr = mask->DataAddress();
         TSize imgSize = mask->SizeInPixels();
         TInt imgByteWidth = imgSize.iWidth >> 3;
         TInt imgBitsLeft = imgSize.iWidth % 8;
         TInt lineLength = CFbsBitmap::ScanLineLength(imgSize.iWidth, dMode);
         TUint8* pCurrByteLine = (TUint8*) imgPtr;
         TUint8 currByte;
         TInt currXPixelOffset;
         TInt currXPixel;
         for (TInt y = 0; y < imgSize.iHeight; y++) {
            for (TInt x = 0; x < imgByteWidth; x++) {
               currByte = pCurrByteLine[x];
               //If currByte is != 0, it contains at least one white pixel.
               if (currByte) {
                  if (ymin > y) {
                     ymin = y;
                  }
                  if (ymax < y) {
                     ymax = y;
                  }
                  currXPixelOffset = x << 3;
                  //Check if this byte of pixels might contain xmin or xmax.
                  if ((currXPixelOffset < xmin) || 
                      ((currXPixelOffset + 7) > xmax)) {
                     for (TInt b = 0; b < 8; b++) {
                        //Some of the 8 pixels in the byte are visible.
                        //Find which ones that mather for the x-axis.
                        if  (currByte & (1 << b)) {
                           currXPixel = currXPixelOffset + b;
                           if (xmin > currXPixel) {
                              xmin = currXPixel;
                           }
                           if (xmax < currXPixel) {
                              xmax = currXPixel;
                           }
                        }
                     }
                  }
               }
            }
            //Here we take care of bit padded bytes when the
            //image width is not evenly dividable by a byte.
            if (imgBitsLeft != 0) {
               currByte = pCurrByteLine[imgByteWidth];
               currXPixelOffset = imgByteWidth << 3;
               for (TInt b = 0; b < imgBitsLeft; b++) {
                  if  (currByte & (1 << b)) {
                     currXPixel = currXPixelOffset + b;
                     if (xmax < currXPixel) {
                        xmax = currXPixel;
                     }
                  }
               }
            }
            //Move to next line in image.
            pCurrByteLine = pCurrByteLine + lineLength;
         }
      }
Exemple #6
0
/*
 * Landmark objects will make use of an SVG file for rendering (demo purposes)
 */
void CLMXObject::ConstructL()
{
    _LIT(KIconFile, "\\resource\\apps\\Landmarks_0x2002E1AF.mif");

    CGulIcon* icon = CreateIconL(KIconFile, EMbmLandmarks_0x2002e1afIcon, EMbmLandmarks_0x2002e1afIcon_mask);
    CleanupStack::PushL(icon);

    CFbsBitmap* bitmap = icon->Bitmap();    // Ownership NOT transferred
    CFbsBitmap* mask   = icon->Mask();      // Ownership NOT transferred

    // Always expect 16M bitmap to make conversion to GL_RGBA easier 
    if (bitmap->DisplayMode() != EColor16M)
    {
        bitmap = new(ELeave) CFbsBitmap;
        CleanupStack::PushL(bitmap);

        User::LeaveIfError(bitmap->Create(icon->Bitmap()->SizeInPixels(), EColor16M));

        CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap);
        CleanupStack::PushL(bitmapDevice);

        CFbsBitGc* bitmapContext = 0;
        User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext));
        CleanupStack::PushL(bitmapContext);

        bitmapContext->BitBlt(TPoint(0, 0), icon->Bitmap());

        CleanupStack::PopAndDestroy(2, bitmapDevice);

        icon->SetBitmap(bitmap);    // Ownership transferred

        CleanupStack::Pop(bitmap);
    }

    // Always expect 256 mask to make conversion to GL_RGBA easier 
    if (mask->DisplayMode() != EGray256)
    {
        mask = new(ELeave) CFbsBitmap;
        CleanupStack::PushL(mask);

        User::LeaveIfError(mask->Create(icon->Mask()->SizeInPixels(), EGray256));

        CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(mask);
        CleanupStack::PushL(bitmapDevice);

        CFbsBitGc* bitmapContext = 0;
        User::LeaveIfError(bitmapDevice->CreateContext(bitmapContext));
        CleanupStack::PushL(bitmapContext);

        bitmapContext->BitBlt(TPoint(0, 0), icon->Mask());

        CleanupStack::PopAndDestroy(2, bitmapDevice);

        icon->SetMask(mask);    // Ownership transferred

        CleanupStack::Pop(mask);
    }

    // Now bitmap and mask point to either original or converted bitmaps, 
    // and ownership belongs to icon

    const TSize bitmapSize = bitmap->SizeInPixels();

    // sizeof(TUint32) == sizeof(RGBA)
    const TInt dataSize = bitmapSize.iWidth * bitmapSize.iHeight * sizeof(TUint32);
    TUint8* data = new(ELeave) TUint8[dataSize];

    // Perform copy and conversion from BGR(A) to RGB(A)
    bitmap->LockHeap();
    mask->LockHeap();

    // TODO: Alpha component removed, as it seems to be corrupted from
    // subsequent reads from SVG file

    TUint8* rgb = reinterpret_cast<TUint8*>(bitmap->DataAddress());
//    TUint8* alpha = reinterpret_cast<TUint8*>(mask->DataAddress());

    for(TInt i = 0, j = 0; i < dataSize; i += 4, j += 3)
    {
        data[i + 0] = rgb[j + 2];
        data[i + 1] = rgb[j + 1];
        data[i + 2] = rgb[j + 0];
        data[i + 3] = 0xc0; //alpha[i / 4];
    }

    // Generate OpenGL texture
    ::glGenTextures(1, &iTextureId); 
    ::glBindTexture(GL_TEXTURE_2D, iTextureId);

    ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmapSize.iWidth, bitmapSize.iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

    mask->UnlockHeap();
    bitmap->UnlockHeap();

    delete data;

    CleanupStack::PopAndDestroy(icon);
}