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; } }
/* * 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); }