在基于linux的嵌入式仿真平台开发中,终端的美观和可定制是一个重要的问题。单调的“白纸黑字”型表现方式可谓大煞风景。改造linux控制台使之美观可定制地展示开机信息和logo成为基于嵌入式linux应用的一项重要工作。

在本节主要讲解如何使用DirectFB来实现开机动画

架构

详细设计

DFB资源初始化

主要使用 DirectFB、Layer、Window、Surface这四种资源,其关系见资料“DirectFB、Layer、Window、Surface之间关系”

    DirectFBInit(&argc, &argv);
DirectFBCreate(&dfb); /* Get the display layer.*/
dfb->GetDisplayLayer(dfb, 0, &layer);
layer->GetConfiguration(layer, &config); /* Create the window. */
layer->CreateWindow(layer, &desc, &window);
window->SetOpacity(window, 0xFF); /* Get the window's surface. */
window->GetSurface(window, surface);

DFB资源释放

    /* Release the window's surface. */
surface->Release(surface);
/* Release the window. */
window->Release(window);
/* Release the layer. */
layer->Release(layer);
dfb->Release(dfb);

图片资源初始化

    DFBSurfaceDescription img_dsc;
IDirectFBImageProvider *provider = NULL; /* 将要显示的图片及其相关信息保存在一个imageprovider中 */
ret = dfb->CreateImageProvider(dfb, filename, &provider); /* 将保存在provider中的图片信息提取出来,存于surface description中 */
ret = provider->GetSurfaceDescription(provider, &img_dsc); /* 根据surface description创建surface,尺寸与图片大小完全一致 */
ret = dfb->CreateSurface(dfb, &img_dsc, surface); /* 将图片呈递给刚才建立的logo平面,如果大小不一致,则进行缩放 */
ret = provider->RenderTo(provider, *surface, NULL); /* release provider */
provider->Release(provider);

图片资源初始化

imgSfc->Release(imgSfc);

动画渲染

static void fillDFBSurface(
IDirectFBSurface *primary_sfc,
IDirectFBSurface *img_sfc,
int x, int y)
{
primary_sfc->Clear(primary_sfc, 0, 0, 0, 255);
/*
* blit即将两张位图(即thiz和source)按拉操作的方法组合成一张图片。
* 在DirectFB中,其定义的动作也是合理的:将img_sfc blit到primary_sfc上去,
* 两个平面上的内容会产生叠加
*/
primary_sfc->Blit(primary_sfc, img_sfc, NULL, x, y);
/* 变换、更新surface buffer */
primary_sfc->Flip(primary_sfc, NULL, DSFLIP_WAITFORSYNC); return ;
}

全文代码示例

/**********************************************
* Author: younger.liucn@hotmail.com
* File name: animation.c
* Description: animation
* Version, Desc
* 1.1 Created
**********************************************/ #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h> #include <time.h>
#include <sys/time.h>
#include <directfb.h> #include <semaphore.h>
#include <signal.h> #include "animation.h" /* config information */
#define ANIM_IMAGES_COUNT 12
/* support png, jpg */
#define ANIM_IMAGE_FORMAT "png"
#define ANIM_FILE_NAME_MAX_SIZE 255
#define ANIM_IMG_DEFAULT_WIDTH 960
#define ANIM_IMG_DEFAULT_HEIGHT 540
#define ANIM_IMG_DEFAULT_FPS 10
#define ANIM_MAX_RUNNING_MTIME (20000) #define ANIM_BLACK_IMAGE "/home/younger/DFB/animApp/images/black.png"
#define ANIM_DEFAULT_LOGO_NAME "/home/younger/DFB/animApp/images/welcome.jpg"
#define ANIM_DEFAULT_LOGO_PATH "/home/younger/DFB/animApp/images/default" /*********************************************************
* log flags and func of debug and error infor.[Begin]
********************************************************/
//#define ANIM_SYS_LAYER
//#define _ANIM_DEBUG_ #ifdef _ANIM_DEBUG_
#define ANIM_DEBUG(format, ...) do { \
printf("[BootAnimation:%4dL]DEBUG: "format, __LINE__, ##__VA_ARGS__); \
} while (0)
#else
#define ANIM_DEBUG(format, ...) do {} while (0)
#endif #define ANIM_NOTICE(format, ...) do { \
printf("[BootAnimation:%4dL]INFO: "format, __LINE__, ##__VA_ARGS__); \
} while (0) #define ANIM_ERROR(format, ...) do { \
printf("[BootAnimation:%4dL]ERROR: "format, __LINE__, ##__VA_ARGS__); \
} while (0) #define DFBCHECK(x...) \
do { \
DFBResult err = x; \
if (err != (DFBResult)DFB_OK) \
{ \
fprintf(stderr, "[%s:%s() L:%u] DFB Error:", __FILE__, __FUNCTION__, __LINE__); \
DirectFBErrorFatal(#x, err); \
} \
} while(0)
/*********************************************************
* log flags and func of debug and error infor.[End]
********************************************************/ /*********************************************************
* Data structure and Global variants [Begin]
********************************************************/
/* 使用directFB画图所需的四个DFB资源 */
struct bootanimation_dsc {
IDirectFB *dfb;
IDirectFBDisplayLayer *layer;
IDirectFBWindow *window;
IDirectFBSurface *surface;
};
static struct bootanimation_dsc badsc; /* 定义图片Surface */
static IDirectFBSurface *imgSfc[ANIM_IMAGES_COUNT];
/*********************************************************
* Data structure and Global variants [End]
********************************************************/ /*********************************************************
* Some functions help animation [Begin]
********************************************************/
/* if exist, return 1; otherwise, return 0. */
static inline int checkFileExist(const char *filename)
{
if((access(filename, R_OK)) != -1)
return 1; return 0;
} /*********************************************************
* Some functions help animation [End]
********************************************************/
void freeResources()
{
/* Release the window's surface. */
if(badsc.surface)
badsc.surface->Release(badsc.surface);
/* Release the window. */
if (badsc.window)
badsc.window->Release(badsc.window);
/* Release the layer. */
if (badsc.layer)
badsc.layer->Release(badsc.layer); badsc.dfb->Release(badsc.dfb); return ;
} static void initResources(int argc, char **argv)
{
DFBResult ret;
badsc.window = NULL;
badsc.surface = NULL;
badsc.dfb = NULL;
IDirectFB *dfb = NULL;
DFBWindowDescription desc;
DFBDisplayLayerConfig config; /* 初始化DirectFB */
DirectFBInit(&argc, &argv);
DirectFBCreate(&dfb);
if (!dfb) {
ANIM_ERROR("directfb interface is NULL\n");
return ;
}
badsc.dfb = dfb; /* 初始化 display layer:其中ANIM_LAYERID_USING设置为0.*/
ret = badsc.dfb->GetDisplayLayer(badsc.dfb, ANIM_LAYERID_USING, &(badsc.layer));
if(ret != (DFBResult)DFB_OK) {
ANIM_ERROR("Get layer(%d) failed!\n", ANIM_LAYERID_USING);
goto fail;
} else {
ANIM_DEBUG("Get layer(%d) independently.\n", ANIM_LAYERID_USING);
} /* 获取display layer的配置,. */
badsc.layer->GetConfiguration(badsc.layer, &config); /* 设置window参数,并创建Window */
desc.flags = (DFBWindowDescriptionFlags)(DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS | DWDESC_OPTIONS);
desc.posx = 0;
desc.posy = 0;
desc.width = config.width;
desc.height = config.height;
desc.caps = (DFBWindowCapabilities)(DWCAPS_NODECORATION);
desc.options = (DFBWindowOptions) (DWOP_GHOST);
ret = badsc.layer->CreateWindow(badsc.layer, &desc, &(badsc.window));
if(ret != (DFBResult)DFB_OK) {
ANIM_ERROR("Create window failed!\n");
goto fail;
} /* 设置透明度 */
ret = badsc.window->SetOpacity(badsc.window, 0xFF);
if(ret != (DFBResult)DFB_OK) {
ANIM_ERROR("SetOpacity failed!\n");
goto fail;
} /* 获取window的surface. */
ret = badsc.window->GetSurface(badsc.window, &(badsc.surface));
if(ret != (DFBResult)DFB_OK) {
ANIM_ERROR("SetOpacity failed!\n");
goto fail;
} return ;
fail:
freeResources();
return ;
} /* free images */
static void deinitImages()
{
int i = 0;
for (i = 0; i <= ANIM_IMAGES_COUNT; i++) {
if (imgSfc[i]) {
imgSfc[i]->Release(imgSfc[i]);
} else {
break;
}
}
return ;
}
static int doLoadImg(const char *filename,
IDirectFBSurface **surface,
unsigned int *width,
unsigned int *height)
{
int ret;
IDirectFB *dfb = badsc.dfb;
DFBSurfaceDescription img_dsc;
IDirectFBImageProvider *provider = NULL; if(NULL == surface || NULL == filename) {
ANIM_ERROR("doLoadImg() failed for %d.\n", -EINVAL);
return -EINVAL;
} ANIM_DEBUG("doLoadImg() entry:%s .\n", filename);
if(!checkFileExist(filename)) {
ANIM_ERROR("file %s does not exist.\n", filename);
return -EINVAL;
} /* 将要显示的图片及其相关信息保存在一个image provider中 */
ret = dfb->CreateImageProvider(dfb, filename, &provider);
if(ret) {
ANIM_ERROR("CreateImageProvider() for %s failed %d.\n", filename, ret);
return ret;
} /* 将保存在provider中的图片信息提取出来,存于surface description中 */
ret = provider->GetSurfaceDescription(provider, &img_dsc);
if(ret) {
ANIM_ERROR("GetSurfaceDescription() for %s failed %d.\n",
filename, ret);
provider->Release(provider);
return ret;
} /* 根据surface description创建surface,尺寸与图片大小完全一致 */
ret = dfb->CreateSurface(dfb, &img_dsc, surface);
if(ret) {
ANIM_ERROR("CreateSurface() for %s failed %d.\n", filename, ret);
provider->Release(provider);
return ret;
} /* 将图片呈递给刚才建立的logo平面,如果大小不一致,则进行缩放 */
ret = provider->RenderTo(provider, *surface, NULL);
if(ret) {
ANIM_ERROR("RenderTo() for %s failed %d.\n", filename, ret);
(*surface)->Release(*surface);
provider->Release(provider);
return ret;
} /* Return width / height? */
if(width) {
*width = img_dsc.width;
}
if(height){
*height = img_dsc.height;
} /* release provider */
provider->Release(provider); ANIM_DEBUG("doLoadImg() exit.\n");
return ret;
} static int initImages()
{
int ret = 0, i = 0;
char filename[ANIM_FILE_NAME_MAX_SIZE];
IDirectFBSurface *tmp_sfc = NULL; for (i = 0; i < ANIM_IMAGES_COUNT; i++) {
imgSfc[i] = NULL;
} for (i = 0; i < ANIM_IMAGES_COUNT; i++) {
tmp_sfc = NULL;
memset(filename, 0x0, sizeof(filename));
snprintf(filename, ANIM_FILE_NAME_MAX_SIZE,
"%s/%d.%s", ANIM_DEFAULT_LOGO_PATH, i, ANIM_IMAGE_FORMAT);
ret = doLoadImg(filename, &tmp_sfc, NULL, NULL);
if (ret != 0) {
goto bail;
}
imgSfc[i] = tmp_sfc;
} return 0;
bail:
deinitImages();
return -1;
} static void fillDFBSurface(
IDirectFBSurface *primary_sfc,
IDirectFBSurface *img_sfc,
int x, int y)
{
primary_sfc->Clear(primary_sfc, 0, 0, 0, 255);
/*
* blit即将两张位图(即thiz和source)按拉操作的方法组合成一张图片。
* 在DirectFB中,其定义的动作也是合理的:将img_sfc blit到primary_sfc上去,
* 两个平面上的内容会产生叠加
*/
primary_sfc->Blit(primary_sfc, img_sfc, NULL, x, y);
/* 变换、更新surface buffer */
primary_sfc->Flip(primary_sfc, NULL, DSFLIP_WAITFORSYNC); return ;
} /* 计算两个时刻的时间差(b-a),单位毫秒 (From kernel) */
static unsigned long deltaMsecs(struct timespec *a,
struct timespec *b)
{
long delta_secs = 0, delta_msecs = 0; if(a->tv_sec < b->tv_sec ||
(a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec)) {
return 0;
} delta_secs = a->tv_sec - b->tv_sec;
delta_msecs = (a->tv_nsec - b->tv_nsec) / 1000000;
while(delta_msecs < 0) {
delta_secs--;
delta_msecs += 1000;
} return delta_secs * 1000 + delta_msecs;
} static void doMovie()
{
int ret, i;
int width = 0, height = 0;
struct timespec before_draw, after_draw;
unsigned long elapsed_msec, total_msec;
IDirectFBSurface *primary = badsc.surface;
IDirectFBSurface *bg_sfc = NULL;
unsigned long interval = (1000 / ANIM_IMG_DEFAULT_FPS); primary->GetSize(primary, &width, &height);
primary->SetColor(primary, 0, 0, 0, 255);
primary->Clear(primary, 0, 0, 0, 255);
primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC); ANIM_NOTICE("Animation start ...\n");
total_msec = 0;
i = 0;
do {
if(i >= ANIM_IMAGES_COUNT) {
i = 0;
} clock_gettime(CLOCK_MONOTONIC, &before_draw);
fillDFBSurface(primary, imgSfc[i],
(width - ANIM_IMG_DEFAULT_WIDTH) / 2,
(height - ANIM_IMG_DEFAULT_HEIGHT) / 2);
clock_gettime(CLOCK_MONOTONIC, &after_draw); elapsed_msec = deltaMsecs(&after_draw, &before_draw);
if(elapsed_msec < interval) {
usleep((interval - elapsed_msec) * 1000);
total_msec += interval;
} else {
total_msec += elapsed_msec;
}
ANIM_DEBUG("elapsed %lu ms \n",
elapsed_msec < interval ? interval : elapsed_msec); if(total_msec >= ANIM_MAX_RUNNING_MTIME) {
ANIM_NOTICE("Stopped by Timeout(%lu).\n", total_msec);
break;
} i++;
} while(1); out:
primary->SetColor(primary, 0, 0, 0, 0);
primary->Clear(primary, 0, 0, 0, 0);
primary->Flip(primary, NULL, DSFLIP_WAITFORSYNC);
ANIM_NOTICE("Animation exit with black screen...\n"); return ;
} static void doAnimation()
{
sem_t *sem_closed = NULL; if (initImages()) {
ANIM_ERROR("Init images failed!\n");
return ;
}
doMovie();
deinitImages(); return ;
} int main(int argc, char **argv)
{
ANIM_NOTICE("Animation entry.\n");
initResources(argc, argv);
doAnimation();
freeResources(); ANIM_NOTICE("Animation exit.\n");
return 0;
}

注意:

/home/younger/DFB/animApp/images/default目录下需要存放0.png~11.png等12张图片

Ok!

DirectFB 之 动画播放初步的更多相关文章

  1. UIImageView~动画播放的内存优化

    我目前学到的知识,播放动画的步骤就是下面的几个步骤,把照片资源放到数组里面,通过动画animationImage加载数组,设置动画播放的 时间和次数完成播放. 后来通过看一些视频了解到:当需要播放多个 ...

  2. unity3d的Animation 动画播放器的基本API

    直接上代码: //动画名称 private const string ANIM_NAME = "Take 001"; //模型对象 private GameObject obj = ...

  3. 关于Unity中如何判断一个动画播放结束

    方法一(强力推荐): 在动画结束帧或其他帧处加个动画事件,在播放到这一帧的时候会自动调用这个动画函数 如图,找到对应动画的inspector面板,在里面有个Events下拉条,下拉后在想要的帧的位置添 ...

  4. 想控制GIF图片动画播放吗?试试gifffer.js

    在线演示:http://www.gbtags.com/gb/demoviewer/3578/c6bec39a-61ae-4017-8e23-e0bc1eeb740f/example|index.htm ...

  5. Delphi 2005 以上版本GIF动画播放设置

    源: Delphi 2005 以上版本GIF动画播放设置

  6. 【转】unity Animator 怎么判断一个动画播放结束

    关于unity Animator 怎么判断一个动画播放结束这里有几种方法.希望对大家有帮助.还有其他办法的可以分享一下 第一种方法:在动画结束帧后面加个动画事件,调用下含这个变量的函数接口不是可以了? ...

  7. UE4]不使用角色蓝图、动画蓝图、状态机,用“24K纯C++”实现动画播放

    http://aigo.iteye.com/blog/2283454 原文作者:@玄冬Wong 不好意思,我稍稍标题党了,目前还不清楚如何用C++代码来实现BlendSpace和Montage的逻辑, ...

  8. (转)在Unity3D中控制动画播放

    用Unity3D也算是好久了,但是每次做项目总还是能学到新的东西.这次做一个TPS的项目就遇到了这样一个问题,如何同时在上下半身播放不同的动画?解决方法其实是很简单,但由于对于动画资源的了解不足导致问 ...

  9. Cocos2d-x动画播放(序列帧)

    简介 Cocos2d-x中,动画的具体内容是依靠精灵显示出来的,为了显示动态图片,我们需要不停切换精灵显示的内容,通过把静态的精灵变为动画播放器从而实现动画效果.动画由帧组成,每一帧都是一个纹理,我们 ...

随机推荐

  1. 10分钟精通SharePoint-搜索

    大势所趋随着企业内容和文档数量的骤增,快速定位到所需材料和内容已经迫不及待,这也是所有企业所面临的共同的挑战,应这个大的趋势,"搜索"闪亮登上了企业协作(SharePoint)舞台 ...

  2. Python中的日期和时间

    感觉C语言作为一门编程的入门语言还是很好的,相比较之下,Python为代表的一些语言,适合很多非计算机专业的编程入门学习. Python 日期和时间 Python 程序能用很多方式处理日期和时间,转换 ...

  3. 开启SQL Server执行占用时间显示和逻辑读取次数显示

    两条命令 1:set statistics time on 这条命令会显示你编译这条语句和执行这条语句花多长时间 2.set statistics io on 这条命令会显示你逻辑读取了多少次数据库和 ...

  4. Authorization user to use specifical database

    DENY VIEW any DATABASE to PUBLIC;ALTER AUTHORIZATION ON DATABASE::Best TO Best

  5. JS和Flash(AS)相互调用

    <!DOCTYPE html> <html> <head> <title>swf</title> <meta charset=&quo ...

  6. Unity 3D Framework Designing(5)——ViewModel之间如何共享数据

    对于客户端应用程序而言,单页应用程序(Single Page Application)是最常见的表现形式.有经验的开发人员往往会把一个View分解多个SubView.那么,如何在多个SubView之间 ...

  7. 浩哥解析MyBatis源码(三)——Transaction事务模块

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6634151.html 1.回顾 之前介绍了Environment环境类,这其实是一个单例类 ...

  8. 《连载 | 物联网框架ServerSuperIO教程》- 17.支持实时数据库,高并发保存测点数据。附:3.4 发布与版本更新说明。

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  9. Android解析xml文件-采用DOM,PULL,SAX三种方法解析

    解析如下xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <perso ...

  10. Jenkins集成Docker

    大概过程如下图: 由于需要用到docker打包镜像,jenkins宿主机上需要安装docker,原先的jenkins server安装在centos6上无法运行docker,所以这里单独用一台cent ...