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中,动画的具体内容是依靠精灵显示出来的,为了显示动态图片,我们需要不停切换精灵显示的内容,通过把静态的精灵变为动画播放器从而实现动画效果.动画由帧组成,每一帧都是一个纹理,我们 ...
随机推荐
- oslo_config中的DuplicateOptError坑
前言: 最近在重写公司的Cinder Driver,我们driver是按照OpenStack的要求,依赖一个叫oslo_config的一个包.这个包的作用就是让driver申明所依赖的选项(可以来自文 ...
- c++ string 对象操作
字符串转换大小写如下: #include "stdafx.h" #include <iostream> #include <string> using na ...
- web从入门开始(1)------简介
服务端与客户端 HTML简介
- ZJOI2017 Day3 滚粗记
私のZJOI Day3 2017-3-21 07:52:53 今天,考了人生当中的第一次省选(虽然只是普及组三等奖但仍然有幸能体会一下).据胡老师说,这就是来体验一下被大神虐--真的是这样,听课听不懂 ...
- HDFS入门(1)
2015.07.12笔记 1.HDFS Distributed File System(操作系统实现人机交互,最重要的功能是文件管理,使用文件管理系统,windows.Linux文件管理系统有共性:用 ...
- iOS开发之数据存储之NSData
1.概述 使用archiveRootObject:toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么就要使用NSData来进行归档对象. NSDat ...
- iOS开发之如何修改导航栏的内容
导航栏的内容由栈顶控制器的navigationItem属性决定. UINavigationItem有以下属性影响着导航栏的内容(通常在子控制器中viewDidLoad方法中调用这些方法): 左上角的返 ...
- [原]node.js使用感想
最近尝试了使用node.js,但因为不是太深入(小项目,还没做完),所以不能谈心得谈经验,就来谈谈使用感想. node.js和以往的cgi接口的服务器+cgi程序(如apache+phpmod)中的单 ...
- js引用类型数组去重-对象标记法
前言 Js数组去重已经有很多种实现方式:包括逐个检索对比(使用Array.property.indexOf),先排序后对比,使用hash表,利用ES6中的Set()等.这些数组去重办法中速度最快的是h ...
- webdriver介绍&与Selenium RC的比较
什么是webdriver? webdriver是一个web自动化测试框架,不同于selenium IDE只能运行在firefox上,webdriver能够在不同的浏览器上执行你的web测试用例.其支持 ...