在基于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. Jmeter 正则提取器

    背景: 用户购买商品,为防止CSRF攻击,在购买请求参数中要携带token参数,token的值是随机加密处理的,每次登录值都会刷新 场景: 用户登录站点,访问商品列表,购买商品 脚本设计: 1.登录 ...

  2. linux版powershell安装教程(.net core版)

    powershell 传教士 原创文章 始于2016-12-20,2017-03-15改.文章版本目前博客园为最新版. 允许转载,但必须保留名字和出处,否则追究法律责任 问:powershell二进制 ...

  3. MySQL常用函数及日期

    一.数学函数 数学函数主要用于处理数字,包括整型.浮点数等. ABS(x) 返回x的绝对值 SELECT ABS(-1) -- 返回1 CEIL(x),CEILING(x) 返回大于或等于x的最小整数 ...

  4. 给 Virtualbox 中 Ubuntu 系统设置静态 IP ,让 DNS 配置信息不会在重启后被清除

    虚拟机网络选择 桥接网卡 模式. 主要涉及两个步骤: 1. 修改 /etc/network/interfaces 文件: 2. 修改 dns : 第一步,修改 interfaces 文件: sudo ...

  5. IOS百度地图之--->第一篇《环境配置与基本使用》

    Ios 百度地图SDK简易使用说明:http://developer.baidu.com/map/index.php?title=iossdk 先道歉:对于原来上传的Demo我很抱歉,什么都没有,也没 ...

  6. PHP的错误处理

    PHP的错误处理机制 php的错误处理是比较复杂的, 本文讲解php中所有错误相关的重要知识点做一次梳理, 便于理解php的错误机制. 基础知识 在此之前, 先熟悉一下php error的基础知识 预 ...

  7. Jenkis Editable Email Notification Plugin 使用介绍

    Jenkis Editable Email Notification Plugin 使用介绍 前言 Jenkins本身提供的Email插件功能实在有限,只能提供当前Job的基本信息,比如成功.失败以及 ...

  8. POJ2352Stars【树状数组】

    Stars Description Astronomers often examine star maps where stars are represented by points on a pla ...

  9. JavaWeb之Cookie和Session的区别

    Cookie和Session的区别 一.cookie机制和session机制的区别 ********************************************************** ...

  10. poptest老李谈分布式与集群 1

    poptest老李谈分布式与集群   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:90882 ...