PrjName = 'swBmpManip' UID = '0x02222227' resource.menu = [['Rotate by 90' , ' iAppView->RotateL( 90 );' ], ['Rotate by 180', ' iAppView->RotateL( 180 );' ], ['Rotate by 270', ' iAppView->RotateL( 270 );' ], ['Save', ' iAppView->SaveL();' ], ['Exit', ' Exit();' ], ] resource.libraries += [ 'fbscli', 'efsrv', 'ws32', 'ImageConversion', 'BitmapTransforms' ] resource.images( ['bmpmanip.gif'], 'gfx_bitmaps' ) appview.inc_inc += [ '"ImageHandlerAO.h"' ] appview.inc_src += [ '', '', ] appview.parent += ', public MImageHandlerCallback' appview.intro_src = r""" // File to load in _LIT(KGifFileName,"c:\\System\\Apps\\$PrjName$\\bmpmanip.gif"); // File to save _LIT(KBmpFileName,"c:\\System\\Apps\\$PrjName$\\newimage.bmp"); // BMP Mime type _LIT8(KBmpMimeType,"image/bmp"); const TDisplayMode KDeviceColourDepth = EColor4K; // Gif file frame index (in this case there is only one frame) const TInt KGifFrameIndex = 0; // New size to scale image const TInt KNewImageWidth = 150; const TInt KNewImageHeight = 150;""" appview.add_notify() appview.add_public( Method( 'void', ('RotateL', 'Rotate the bitmap clockwise'), [Arg('TInt', 'aAngle', 'an angle to rotate')], """\ if (iImageHandler->IsActive()) { // Inform the UI that the gif file is still being loaded User::Leave(KErrInUse); } iImageHandler->FrameRotate( aAngle );""") ) appview.add_public( Method( 'void', ('SaveL', 'Save the bitmap to a new file'), [], """\ iImageHandler->SaveFileL( KBmpFileName, KBmpMimeType );""") ) appview.add_private( Var( 'CFbsBitmap*', 'iBitmap', 'The bitmap being displayed' ), True ) appview.add_public( Var( 'CImageHandler*', 'iImageHandler', 'For file access and manipulation' ), True ) appview.members['Draw'].code += """ // If the bitmap is not currently being processed in any way if (!iImageHandler->IsActive()) { gc.BitBlt( Rect().iTl, iBitmap ); }""" appview.members['ConstructL'].code += """ iBitmap = new (ELeave) CFbsBitmap(); iBitmap->Create( TSize(0,0), EColor256 ); iImageHandler = CImageHandler::NewL( *iBitmap, iEikonEnv->FsSession(), *this ); // Start an asynchronous process to open the gif file iImageHandler->LoadFileL( KGifFileName );""" appview.add_private( Method( 'void', ('ImageOperationComplete', 'Callback, operation done'), [ Arg( 'TInt', 'aError', '' ) ], """\ User::LeaveIfError( aError ); DrawNow();""" ) ) imghandler = CClass( ('ImageHandlerAO', 'Loads, saves, and manipulates a bitmap') ) imghandler.inc_inc += [ ' // Font and bitmap server', ' // Image converter library API header', ' // Bitmap transforms API header' ] imghandler.intro_inc = """ // Callback from image handler class MImageHandlerCallback { public: // Handler calls when image manipulation is completed virtual void ImageOperationComplete(TInt aError) = 0; }; """ imghandler.make_active( [ Arg('CFbsBitmap &', 'aBitmap', ''), Arg('RFs &', 'aFs', ''), Arg('MImageHandlerCallback &', 'aCallback', '') ], 'iBitmap(aBitmap), iFs(aFs), iCallback(aCallback)', ph1_code = '', ph2_code = """\ iBitmapRotator = CBitmapRotator::NewL(); iBitmapScaler = CBitmapScaler::NewL();""", runl_code = """\ // Operation complete, call back caller iCallback.ImageOperationComplete( iStatus.Int() );""", docancel_code = """\ // Cancel everything possible if (iLoadUtil) iLoadUtil->Cancel(); if (iSaveUtil) iSaveUtil->Cancel(); iBitmapRotator->Cancel(); iBitmapScaler->Cancel();""" ) imghandler.add_public( Method( 'void', ( 'LoadFileL', 'Load operation' ), [ Arg('const TDesC&', 'aFileName', ''), Arg('TInt', 'aSelectedFrame = 0', '') ], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // create a CImageDecoder to read the specified file delete iLoadUtil; iLoadUtil = NULL; iLoadUtil = CImageDecoder::FileNewL( iFs, aFileName ); // store the frame information and frame count iFrameInfo = iLoadUtil->FrameInfo( aSelectedFrame ); iFrameCount = iLoadUtil->FrameCount(); // resize the destination bitmap to fit the required size TRect bitmapSize = iFrameInfo.iFrameCoordsInPixels; iBitmap.Resize( bitmapSize.Size() ); // start reading the bitmap: RunL called when complete iLoadUtil->Convert( &iStatus, iBitmap, aSelectedFrame ); SetActive();""" ) ) imghandler.add_public( Method( 'void', ( 'SaveFileL', 'Save operation' ), [ Arg('const TDesC&', 'aFileName', ''), Arg('const TUid&', 'aImageType', ''), Arg('const TUid&', 'aImageSubType', '') ], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // create a CImageEncoder to save the bitmap to the specified file in the specified format delete iSaveUtil; iSaveUtil = NULL; iSaveUtil = CImageEncoder::FileNewL( iFs, aFileName, CImageEncoder::EOptionNone, aImageType, aImageSubType ); // start saving the bitmap: RunL called when complete iSaveUtil->Convert( &iStatus, iBitmap ); SetActive();""" ) ) imghandler.add_public( Method( 'void', ( 'SaveFileL', 'Save operation' ), [ Arg('const TDesC&', 'aFileName', ''), Arg('const TDesC8&', 'aMimeType', 'E.g., image/jpeg, image/gif, ...') ], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // create a CImageEncoder to save the bitmap to the specified file in the specified format delete iSaveUtil; iSaveUtil = NULL; iSaveUtil = CImageEncoder::FileNewL( iFs, aFileName, aMimeType, CImageEncoder::EOptionNone ); // start saving the bitmap: RunL called when complete iSaveUtil->Convert( &iStatus, iBitmap ); SetActive();""" ) ) imghandler.add_public( Method( 'void', ( 'FrameRotate', '' ), [ Arg('TInt', 'aAngle', 'Rotation angle in degrees: 90, 180, or 270.') ], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // start rotating the bitmap: RunL called when complete switch (aAngle) { case 90: { iBitmapRotator->Rotate(&iStatus, iBitmap, CBitmapRotator::ERotation90DegreesClockwise); break; } case 180: { iBitmapRotator->Rotate(&iStatus, iBitmap, CBitmapRotator::ERotation180DegreesClockwise); break; } case 270: { iBitmapRotator->Rotate(&iStatus, iBitmap, CBitmapRotator::ERotation270DegreesClockwise); break; } default: ASSERT(FALSE); } SetActive();""" ) ) imghandler.add_public( Method( 'void', ( ' Mirror', '' ), [], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // start rotating the bitmap: RunL called when complete iBitmapRotator->Rotate( &iStatus, iBitmap, CBitmapRotator::EMirrorVerticalAxis ); SetActive();""" ) ) imghandler.add_public( Method( 'void', ( 'Flip', '' ), [], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // start rotating the bitmap: RunL called when complete iBitmapRotator->Rotate( &iStatus, iBitmap, CBitmapRotator::EMirrorHorizontalAxis ); SetActive();""" ) ) imghandler.add_public( Method( 'void', ( 'ZoomFrame', '' ), [ Arg('TBool', 'aZoomIn', '') ], """\ __ASSERT_ALWAYS( !IsActive(), User::Invariant() ); // Determine target zooming size TSize size( iBitmap.SizeInPixels() ); const TSize adjust( size.iWidth/2, size.iHeight/2 ); if ( aZoomIn ) size += adjust; else size -= adjust; // Don't let it go too small if (size.iWidth < 10) size.iWidth = 10; if (size.iHeight < 10) size.iHeight = 10; // start scaling the bitmap: RunL called when complete iBitmapScaler->Scale( &iStatus, iBitmap, size ); SetActive();""" ) ) imghandler.add_public( Method( 'const TFrameInfo&', ( 'FrameInfo', '' ), [], 'return iFrameInfo;', is_const = True ) ) imghandler.add_public( Method( 'TInt', ( 'FrameCount', '' ), [], 'return iFrameCount;', is_const = True ) ) imghandler.add_private( Var( 'MImageHandlerCallback &', 'iCallback', 'Callback interface' ) ) imghandler.add_private( Var( 'CFbsBitmap &', 'iBitmap', 'Bitmap' ) ) imghandler.add_private( Var( 'RFs &', 'iFs', 'File server handle' ) ) imghandler.add_private( Var( 'TFrameInfo', 'iFrameInfo', 'Frame information' ) ) imghandler.add_private( Var( 'TInt', 'iFrameCount', 'Frame count' ) ) imghandler.add_private( Var( 'CImageDecoder *', 'iLoadUtil', 'Image file loader' ), destroy_var = True ) imghandler.add_private( Var( 'CImageEncoder *', 'iSaveUtil', 'Image file saver' ), destroy_var = True ) imghandler.add_private( Var( 'CBitmapRotator *', 'iBitmapRotator', 'Bitmap rotator' ), destroy_var = True ) imghandler.add_private( Var( 'CBitmapScaler *', 'iBitmapScaler', 'Bitmap zoomer' ), destroy_var = True )