首 页 | 新 闻 | Symbian | Windows Mobile| J2ME | 下载中心 | 游戏策划 | 购书指南 | 移动开发视频教程
您现在的位置: 开发视界 >> 专家专栏 >> 剑走偏锋 >> 文章正文
Graphics(4)
作者:剑走偏锋    文章来源:本站原创    更新时间:2005-8-9 15:27:15
    这几天总忙,字体那一部分,翻译了三天,进度实在有点慢.今天大概没啥事情了,暂时决定去杭州了,感觉那面还不错,经理很和蔼,他们的技术也正是我想要的.

    在Symbian系统中,首选的使用Bitmap的方法是创建一个MBM(Multi-Bitmap file),在程序运行的时候从MBM中载入.一个MBM可以是一个文件存储器,或者只读镜像(ROM image)类型.文件存储器类型的MBM会被压缩,在程序运行的时候需要解压缩,消耗资源,只读镜像类型的MBM不被压缩,直接调用,节省资源.默认的MBM是文件存储器类型.

    MBM可以从Windows的Bitmap中创建,使用bmconv工具进行转换.MBM可以直接被命令行所使用,或在mmp文件中定义.在编译的时候,他会被拷贝到相应的目标文件夹下.示例代码:
以下内容为程序代码:

// MyGame.mmp

START BITMAP        MyGame.mbm

HEADER

TARGETPATH          ..\..\..\..\wins\c\system\apps\MyGame

SOURCEPATH          ..\MyBitmaps

//                  color-depth   source-bitmap

SOURCE              c12           image1.bmp

SOURCE              c12           image2.bmp

SOURCE              c12           image3.bmp

END

以下内容为程序代码:

    mmp在Bitmap的.h文件里给其一个枚举型的ID的数字,这个ID数字产生在系统文件夹下,(epoc32\include).Bitmap文件可以使用其ID数字在mbm文件中被存取,每一个ID都以下面的格式构造EMbm<MBM file name><bitmap file name>, 例如EMbmMygameImage1.如下存取MBM文件示例:
[img]http://images.blogcn.comude <MyGame.mbg> // generated on compilation

[/img]include <aknutils.h> // for CompleteWithAppPath()

 

CFbsBitmap* CMyGameView::LoadMyBitmapL()

   {

   // set the name of the multi-bitmap file containing the bitmaps

   _LIT(KMBMFileName,"MyGame.mbm"[img]/images/wink.gif[/img];

   TFileName mbmFileName(KMBMFileName);

   CompleteWithAppPath(mbmFileName);

 

   // load the bitmap from the mbm file

   CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();

   CleanupStack::PushL(bitmap);

   // EMbmMygameImage1 is enumerated value from MyGame.mbg file

   User::LeaveIfError(bitmap->Load(mbmFileName, EMbmMygameImage1));

   CleanupStack::Pop(); // bitmap

 

   return bitmap;

   }

    当Bitmap被载入以后,他可以被输出显示,如下示例代码:
void CMyGameView:[img]/images/biggrin.gif[/img]raw( const TRect& /*aRect*/ [img]/images/wink.gif[/img] const

   {

   // Get the system graphics context

   CWindowGc& gc = SystemGc();

 

   // Draw the bitmap

   gc.BitBlt( TPoint(10, 10), iMyShipBitmap);

   }

    通常在一些情况下会用到遮挡.遮挡其实就是以遮挡的方法,来显示黑色和白色的图片.默认设置黑色部分是显示部分,白色是遮挡部分.有一些方法也可以实现反相遮挡.遮挡和普通的显示图片其实是一样的,也需要载入.遮挡示例代码:
以下内容为程序代码:

void CMyGameView:[img]/images/biggrin.gif[/img]raw( const TRect& /*aRect*/ [img]/images/wink.gif[/img] const

   {

   // Get the system graphics context

   CWindowGc& gc = SystemGc();

 

   // Draw masked bitmap

   gc.BitBltMasked( TPoint(10, 10), iMyShipBitmap, iMyShipRect, 

         iMyShipMask, EFalse);

   }

    遮挡对于游戏来说是非常有用的,你可以通过遮挡在背景上显示一些不规则的图形或图像.

    在图像显示过程中,有时候要同时显示出几张图像来,这样会是一个很消耗系统资源的事情.这就会导致系统在显示图像的情况下比较缓慢,而且图像也是从不完整或者不准确到准确这样的一个显示过程.虽然最后的显示结果是准确的,但是,我们通常使用另外一种方法来避免这种情况.我们通常来建立一个容器类来控制图片的显示,转化和储存.
    
    图片的转化可以使用一个临时的Bitmap来实现,示例代码如下:
以下内容为程序代码:

CFbsBitmap* CMyGameView::LoadAndConvertBitmapL( 

   Const TDesC& aFileName, TInt aBitmapId [img]/images/wink.gif[/img]

   {

   // Load the original bitmap

   CFbsBitmap* originalBitmap = new ( ELeave [img]/images/wink.gif[/img] CFbsBitmap();

   CleanupStack::PushL( originalBitmap [img]/images/wink.gif[/img];

   User::LeaveIfError( originalBitmap->Load( aFileName, aBitmapId, 

      EFalse [img]/images/wink.gif[/img] [img]/images/wink.gif[/img];

 

   // Create a new bitmap, graphics device and context

   CFbsBitmap* newBitmap = new ( ELeave [img]/images/wink.gif[/img] CFbsBitmap();

   CleanupStack::PushL( newBitmap [img]/images/wink.gif[/img];

   newBitmap->Create( originalBitmap->SizeInPixels(), 

      Window()->DisplayMode() [img]/images/wink.gif[/img];

   CFbsBitmapDevice* graphicsDevice = CFbsBitmapDevice::NewL(

      bitmapConverted [img]/images/wink.gif[/img];

   CleanupStack::PushL( graphicsDevice [img]/images/wink.gif[/img];

   CFbsBitGc* graphicsContext;

   User::LeaveIfError( graphicsDevice->CreateContext(

      graphicsContext [img]/images/wink.gif[/img] [img]/images/wink.gif[/img];

 

   // Blit the loaded bitmap to the new bitmap (the actual 

   // conversion)

   bitmapContext->BitBlt( TPoint(0,0), originalBitmap [img]/images/wink.gif[/img];

 

   CleanupStack::Pop(3);

   delete bitmapContext;

   delete bitmapDevice;

   delete originalBitmap;

   return newBitmap;

   }

    上面的例子通过参数来获得文件名和Bitmap的ID,从MBM文件中载入相应的Bitmap.转化Bitmap为windows的显示模式,使用新的Bitmap来显示.

    Bitmap可以旋转和块状化,这也是很有用处的.CMdaBitmapRotator来实现旋转一定的角度,CMdaBitmapScaler来实现块状化.S60平台2.0以前的版本不支持这两种方法,他使用了这两种CbitmapRotator
和CbitmapScaler,实现的功能是一样的.

    实际上这两种方法的执行是异步的,通过继承自MMdaImageUtilObserver一个类来通知操作完成.如果你觉得对于Bitmap的操作方法太少,你也可以使用或者定义其他新的.If speed is a critical factor, you can access the bitmap data directly with a pointer and modify it as needed. 

    你可以使用CFbsBitmap:ataAddress来直接存取Bitmap数据区域的头指针(最左上角第一个点).有一点要注意,在程序运行的时候,这个点可能会被移动.所以,在对其使用TBitmapUtil进行存取的时候,要进行锁定.在S60平台2.0里,我们使用CFbsBitmap的LockHeap和UnlockHeap的方法.

    在对Bitmap数据直接访问的时候,你需要知道他们的格式,比如,16比特的Bitmap是5-6-5格式,而12比特的Bitmap是4-4-4的格式.下面示例代码演示了给所有象素加上一个红色部分:
以下内容为程序代码:

void CMyGameView:[img]/images/biggrin.gif[/img]oMyBitmapEffect(CFbsBitmap* aBitmap) 

   {

   // Lock heap

   // For series 60 2.0 use:

   // aBitmap->LockHeap();

   // For series 60 1.0 use:

   TBitmapUtil bitmapUtil(aBitmap);

   bitmapUtil.Begin( TPoint(0,0) [img]/images/wink.gif[/img];

 

   // Edit bitmap

   TSize bitmapSize = aBitmap->SizeInPixels();

   // NOTE: TUint16* applies to 16bit bitmaps only; the pointer must

   // correspond the bit depth of the bitmap.

   TUint16* bitmapData = (TUint16*)aBitmap->DataAddress();

   for ( TInt y = 0; y < bitmapSize.iHeight; y++ [img]/images/wink.gif[/img];

      {

      for ( TInt x = 0; x < bitmapSize.iWidth; x++ [img]/images/wink.gif[/img]

         {

         // Increase colour value of each pixel by one

         *bitmapData = ( *bitmapData & 31 [img]/images/wink.gif[/img] | // blue

                        ( ( *bitmapData >> 5 [img]/images/wink.gif[/img] & 63 [img]/images/wink.gif[/img] | // green

                        ( ( *bitmapData >> 11 [img]/images/wink.gif[/img] & 31 + 1 [img]/images/wink.gif[/img]; // red

         bitmapData++;

         }

      }

   // Unlock heap

   // For series 60 1.0 use:

   bitmapUtil.End();

   // For series 60 2.0 use:

   // aBitmap->UnlockHeap();

   }

    最后,Hardware Acceleration里面给我们提供了很多好东东.
相关文章:
Symbian sdk帮助-术语表B
创建.mbm文件
控制与复合控制
Graphics(2)
Graphics(3)
Graphics(5)
Graphics(7)