DirectFB 之 动画播放初步
在基于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 之 动画播放初步的更多相关文章
- UIImageView~动画播放的内存优化
我目前学到的知识,播放动画的步骤就是下面的几个步骤,把照片资源放到数组里面,通过动画animationImage加载数组,设置动画播放的 时间和次数完成播放. 后来通过看一些视频了解到:当需要播放多个 ...
- unity3d的Animation 动画播放器的基本API
直接上代码: //动画名称 private const string ANIM_NAME = "Take 001"; //模型对象 private GameObject obj = ...
- 关于Unity中如何判断一个动画播放结束
方法一(强力推荐): 在动画结束帧或其他帧处加个动画事件,在播放到这一帧的时候会自动调用这个动画函数 如图,找到对应动画的inspector面板,在里面有个Events下拉条,下拉后在想要的帧的位置添 ...
- 想控制GIF图片动画播放吗?试试gifffer.js
在线演示:http://www.gbtags.com/gb/demoviewer/3578/c6bec39a-61ae-4017-8e23-e0bc1eeb740f/example|index.htm ...
- Delphi 2005 以上版本GIF动画播放设置
源: Delphi 2005 以上版本GIF动画播放设置
- 【转】unity Animator 怎么判断一个动画播放结束
关于unity Animator 怎么判断一个动画播放结束这里有几种方法.希望对大家有帮助.还有其他办法的可以分享一下 第一种方法:在动画结束帧后面加个动画事件,调用下含这个变量的函数接口不是可以了? ...
- UE4]不使用角色蓝图、动画蓝图、状态机,用“24K纯C++”实现动画播放
http://aigo.iteye.com/blog/2283454 原文作者:@玄冬Wong 不好意思,我稍稍标题党了,目前还不清楚如何用C++代码来实现BlendSpace和Montage的逻辑, ...
- (转)在Unity3D中控制动画播放
用Unity3D也算是好久了,但是每次做项目总还是能学到新的东西.这次做一个TPS的项目就遇到了这样一个问题,如何同时在上下半身播放不同的动画?解决方法其实是很简单,但由于对于动画资源的了解不足导致问 ...
- Cocos2d-x动画播放(序列帧)
简介 Cocos2d-x中,动画的具体内容是依靠精灵显示出来的,为了显示动态图片,我们需要不停切换精灵显示的内容,通过把静态的精灵变为动画播放器从而实现动画效果.动画由帧组成,每一帧都是一个纹理,我们 ...
随机推荐
- 2017-3-20 HTML 基础知识
HTML的定义:HTML是一门编程语言的名字:超文本标记语言(Hyper Text Mark-up Language ),就是超越了文字的范畴,除了文字还可以有图片.视频.音频.动画.特效.表格.链接 ...
- docker工作流程
Docker提供一种方法在容器中运行安全隔离的应用程序,应用程序与所有依赖项和库一起打包在容器中.因为你的应用程序总是可以使用它在构建镜像中期望的环境运行,测试和部署比以往任何时候都更简单,因为你的构 ...
- 隐式的处理SOAPHeader消息
先用一下比较基础的隐式方式处理我的SOAPHeader消息,注意的是QName的使用,代码如下: public static void main(String[] args) { try { //创建 ...
- iOS开发优秀博客和软件推荐
iOSBlogAndTools iOS开发优秀博客和软件推荐 本博客和工具列表由广大iOS开发者收集和推荐,如果大家有好的博客或者工具想要分享请点击:我要提交. 收到大家的提交后会及时收录与更新.Gi ...
- 20155304 2016-2017-2 《Java程序设计》第五周学习总结
20155304 2016-2017-2 <Java程序设计>第五周学习总结 教材学习内容总结 第八章 try catch JVM会先尝试执行try区块中的内容,若发生错误且与catch后 ...
- 跨站的艺术-XSS Fuzzing 的技巧
作者 | 张祖优(Fooying) 腾讯云 云鼎实验室 对于XSS的漏洞挖掘过程,其实就是一个使用Payload不断测试和调整再测试的过程,这个过程我们把它叫做Fuzzing:同样是Fuzzing, ...
- swfobject.js加载swf,关于是否加加载完成;
这几个帖子可以参考下 http://bbs.9ria.com/forum.php?mod=viewthread&page=1&tid=38913 http://bbs.9ria.com ...
- 整合第二次(SSM第一次)------------>spring+struts2+mybatis
今天我们来讲解一下SSM整合,感觉整合这个比上一篇整合更费时,原因在于自己不太熟悉MyBatis了,下午的时候恶补了一下,看了一下相关的文档和PDF电子书,知识真的是你不用就会忘记的,以后还是不能懈怠 ...
- WebService基础学习(三)—CXF
一.什么是CXF? Apache CXF = Celtix + Xfire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF.Apache ...
- cssreset
/** * http://cssreset.com */html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, ...