Chinaunix首页 | 论坛 | 博客
  • 博客访问: 40763
  • 博文数量: 18
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 200
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-05 10:27
文章分类
文章存档

2011年(1)

2009年(1)

2008年(16)

我的朋友

分类: C/C++

2009-01-04 14:11:26

一、图片资源

最基础的时钟单元,需要一个背景,两个或三个指针(时针跟分针是需要的,秒针可视客户需要而定)。一个针我们只需要 1 张即可,最好是指向12 点钟的那一帧,这样我们计算坐标及生成其他帧都会比较方便。

另外,原始的图片,针与背景的比例,最好是已经是匹配的,否则需要先加工,以避免strech 时候产生变形影响画面质量。如现有图片资源如下:

 

二、图片处理   

紧接着我们要对图片做处理,主要是针对 3 张指针图片,每张处理成15 帧(即从 12 点到 3 点的方向,共 15 个不同角度,每个角度对应一张指针。其他区间,使用软体对这15 帧去做镜像处理即可得到),因为时、分、秒针的处理都一样,所以只详细列举一种,举一反三可知其他针的处理。拿秒针处理,过程如下:

l         先拿出原始的秒针图片,处理成 ARGB4444的格式(也可以处理成ARGB8888,但是那样会占用多很多空间,以致使用的时候需要的SDRAM 也增加了,所以一般用ARGB4444 即可满足要求)。

l         原始图片转成 ARGB4444 的图片,需要对其增加一个Alpha ChannelAlpha Channel 这个数据,是软体控制透明范围的基础,一般的做法是:在Alpha Channel里面,被黑色(0xFF)盖住的地方,完全透明;被白色盖住的地方(0x00),完全不透明;其他颜色按其灰度线性计算其透明度。强烈建议Alpha Channel 由美工去完成,这样比较保证质量。如图片较简单需软体自行完成,可参考以下步骤:

1、先选择魔棒,设置其属性如下图(容差决定了物件边缘模糊的范围,如物件较大或希望有更多自然过度的效果,可加大容差)

   2、点选图片,选出要透明的地方
   3、新建一个Alpha Channel,设置好前后背景颜色,反选(ctr+shift+I)
    4、删除选中区域里面的颜色(变白色),从下图可以看到,因为我们刚才做了 1 个点的容差,会造成Alpha Channel 里面边缘的地方有些从白到黑的过度的点。其实这个正是我们想要的效果,因为如果没有容差,那么黑就是黑,白就是白,这样就会造成图片边缘的地方会很多明显的锯齿!但实际上,对于物体边缘的点,要显示,还是要透明,其实是很难取舍的,所以不如让他半透明的过来来得好。
 

l         接着,抓出其旋转中心,然后使用工具rotate_image.exe,得出旋转其他角度后的图片

特别主要到下面有个 MinPin_center.c,这个文件也是在我们使用 rotate_image.exe 的时候自动生成的,他记录了每一帧图片的中心位置坐标,这为我们后续的开发提供了极大的便利!

将上面选中的图片拉到photoshop 里面,可以看到图片已经转好了(但是ARGB4444 在windows 里面看不到预览,用普通的看图工具也看不到,需要在photoshop 里才可以)

三、将图片资源传给软体使用

l         先将图片资源 copy \data\bitmap_800x480 下面。因为指针太多,所以建议在这里专门建一个文件夹来存放,我在这里建了一个名为 clock 的文件夹。

l         然后,修改 install 下相应的 cmd。例如我做的是320*240 的系统,所以要在320x240.cmd 这个批处理里面去编码导入。主要增加以下几行

mkdir temp\clock

copy %SRC_DIR%\bitmap_800x480\clock\*.bmp temp\clock

 

cd clock

for %%f in (*.bmp) do ..\..\..\tool\bin\dataconv -b %%f

cd..

copy /b clock\HrPin_0000.bin + clock\HrPin_0001.bin ^

        + clock\HrPin_0002.bin + clock\HrPin_0003.bin + clock\HrPin_0004.bin + clock\HrPin_0005.bin + clock\HrPin_0006.bin ^

        + clock\HrPin_0007.bin + clock\HrPin_0008.bin + clock\HrPin_0009.bin + clock\HrPin_0010.bin + clock\HrPin_0011.bin ^

        + clock\HrPin_0012.bin + clock\HrPin_0013.bin + clock\HrPin_0014.bin  ^

        + clock\MinPin_0000.bin + clock\MinPin_0001.bin + clock\MinPin_0002.bin + clock\MinPin_0003.bin + clock\MinPin_0004.bin ^

        + clock\MinPin_0005.bin + clock\MinPin_0006.bin + clock\MinPin_0007.bin + clock\MinPin_0008.bin + clock\MinPin_0009.bin ^

        + clock\MinPin_0010.bin + clock\MinPin_0011.bin + clock\MinPin_0012.bin + clock\MinPin_0013.bin + clock\MinPin_0014.bin ^

        + clock\SecPin_0000.bin + clock\SecPin_0001.bin + clock\SecPin_0002.bin + clock\SecPin_0003.bin + clock\SecPin_0004.bin ^

        + clock\SecPin_0005.bin + clock\SecPin_0006.bin + clock\SecPin_0007.bin + clock\SecPin_0008.bin + clock\SecPin_0009.bin ^

        + clock\SecPin_0010.bin + clock\SecPin_0011.bin + clock\SecPin_0012.bin + clock\SecPin_0013.bin + clock\SecPin_0014.bin ^

        ..\%DEST_DIR%\NAND_PRIVATE\smediadata\clock5.bin

l         这样,就把图片资源,全部打包在 clock5.bin 里面,并且放到了 smediadata 里。

l         接着,为了软体方便的调用到这些数据,我们应该对 resource.cresource.hresource_dynamic.cresource_static.c做相应的修改,具体细节可以参考其他UI图片,依样画葫芦即可。

四、软体编程部分

事实上时钟单元跟其他单元的编程过程是一样的,思想也是一样的,唯一比较麻烦的,是指针坐标的抓取。

l         为保证指针变化的顺畅,我们直接将所有指针,一次性全部load SDRAM里面去。(这里因为是320*240,所以针都很短。如果指针很长,会造成SDRAM 的大量占用,可考虑只对秒针做这样的处理,时针与分针,每次只load 两张,在合适的时候做切换)。相关代码如下:

static SMTK_BITMAP imgHrPin[15], imgMinPin[15],imgSecPin[15];

static MMP_SURFACE  surfHrPin[15], surfMinPin[15], surfSecPin[15];

……

    smtkResMgrInitialize(SMTK_RES_CLOCK5);

   for(i=0;i<15;i++)

  {

        smtkResMgrGetBitmap(SMTK_CLOCK_HR_PIN_D00+i, &imgHrPin[i]);

         smtkResMgrGetBitmap(SMTK_CLOCK_MIN_PIN_D00+i, &imgMinPin[i]);

         smtkResMgrGetBitmap(SMTK_CLOCK_SEC_PIN_D00+i, &imgSecPin[i]);

 }

 for(i=0;i<15;i++)

{

      result = mmpM2dCreateSurfaceFromImage(

                            imgHrPin[i].width, imgHrPin[i].height, imgHrPin[i].width*2,

                            MMP_ARGB4444, imgHrPin[i].data, &surfHrPin[i]);   

      result = mmpM2dCreateSurfaceFromImage(

                            imgMinPin[i].width, imgMinPin[i].height, imgMinPin[i].width*2,

                            MMP_ARGB4444, imgMinPin[i].data, &surfMinPin[i]);   

      result = mmpM2dCreateSurfaceFromImage(

                            imgSecPin[i].width, imgSecPin[i].height, imgSecPin[i].width*2,

                            MMP_ARGB4444, imgSecPin[i].data, &surfSecPin[i]);   

}           

PS:记住这里申请的 surf,在Terminate 的时候,都要 Delete 掉!否则会造成大量的内存泄漏,估计进出多几次,机器就挂掉了。

l         smtkClock5MgrDraw,这个函数是模式时钟单元的主体,一般它的过程是(这里先以秒针为例,分针参考秒针即可,时针只有 0-24 这些个值,并且时针会受分针的影响,例如12 点半的时候,时针不应该正对着12 点的方向,而是要先 1 点钟的方向偏一半,放到后面讨论):

n         先用smtkRtcMgrGetTime(&clock5Mgr.hour, &clock5Mgr.min, &clock5Mgr.sec);得到当前的时间的数据,存到 clock5Mgr.hourclock5Mgr.minclock5Mgr.sec 中(当然也可以自己定义其他变量来存)。

n         上面得到当前的秒数,放到 clock5Mgr.sec 里面。故秒针的角度,方向,位置,都已经是固定下来的,我们需针对 4 个象限分情况做讨论。最简单的,是0-14 秒,参考以下代码:

              if(sec<15)

              {

             result = mmpM2dAlphaBlendDisableDither(

                                 surf,

                                CLOCK_CENTER_X-SecCenter[sec][0],                                            

                                CLOCK_CENTER_Y-SecCenter[sec][1],

                                imgSecPin[sec].width,

                                imgSecPin[sec].height,

                                surfSecPin[sec],0,0,     

                                MMP_M2D_ABLEND_FORMAT_SRC_ALPHA, 0xFF);

              }

        其中,SecCenter[][] 这个二维数组,记录的是指针的中心(指针在旋转后,其中心位置坐标有变化!)这个数组是 rotate_image.exe 生成的。

 

        再看15-29 的情况:

     else if((sec>=15) && (sec <30))

     {

             result = mmpM2dSetRotateOp(surf, MMP_M2D_ROTATE_OP_90);

             result = mmpM2dAlphaBlendDisableDither(

                 surf,

                 CLOCK_CENTER_X+SecCenter[sec%15][1]-imgSecPin[sec%15].height, 

                 CLOCK_CENTER_Y-SecCenter[sec%15][0],   

                  imgSecPin[sec].width,

                  imgSecPin[sec].height,

                  surfSecPin[sec],0,0,  

                  MMP_M2D_ABLEND_FORMAT_SRC_ALPHA, 0xFF);

    }

result = mmpM2dSetRotateOp( surf, MMP_M2D_ROTATE_OP_NOT);

PalAssert(result == MMP_SUCCESS);

                     代码结合图片可知道:因为 SecCenter[ ][ ] 这个数组是固定死的,imgSecPin[ ].height imgSecPin[ ].width 也是固定死的,就是说一但你取了这一张图,那么他的高跟宽就定下来了,不会因为你把图片旋转90度,就使得imgSecPin[ ].height 取到的值是图的宽!

对于时针的,我们也让其旋转 1 圈的时候,总共跳60 格,所以只需在前面加这一段:

              if(hour>=12)

                     hour-=12;

              hour = (hour*5)+(min/12);

后面的关于时针的做法,就可以完全按照秒针那样来了!

 

五、时钟问题的扩展

有些时钟,会加一些动态的元素做修饰,例如转动的齿轮,晃动的钟摆等等,这些跟普通的UI 显示方法是一样的,只是要主要几个地方:1、动态:可以使用计数方式,通过循环切换实现动态效果;2、计算好坐标;3、刷新图片的先后顺序会造成图层的前后(即谁遮住谁的效果),一般先被刷新的元素,显示在低下,后被刷新的,盖住前面已经刷新的。

 

 

 

阅读(1331) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-10-27 20:15:11

hao