DirectFB 之 分段动画
动画动态配置
一套素材的目录结构一般如下:
子目录中的图片名称都是以数字命名,比如,1,2, 3, 4,……
而配置文件animation.cfg的格式如下:
#width height fps
960 540 10
#type isPlay startIndex endIndex maxTime partChildPath
png 1 1 1 4000 part0
png 1 1 12 25000 part1
上述配置文件中,有两类参数:
第一类参数,表示整个开机动画的参数
width height fps
width:图片的宽度;
height:图片的宽度,这里图片尺寸为960*540,宽为960,高为540;
fps:图片的切换速率,比如参数10,表示每一秒切换10张图片
第二类参数,表示该子目录下的图片的运行模式:
type isPlay startIndex endIndex maxTime partChildPath
type:图片格式,比如png,jpg
isPlay:动画是否播放该子目录,0-不包括,1-不包括
startIndex:第一个显示的图片
endIndex:最后一个显示的图片
maxTime:最大运行时间
partChildPath:子目录的名称
数据结构 HeadNode
标识:head
类型:struct HeadNode
含义:用于标识动画所需图片的宽与高及其刷新频率。
Data Type |
Data Item Definition |
Data Item Description |
int |
fps |
动画刷新频率 |
int |
imgWidth |
动画所用图片的宽 |
int |
imgHeight |
动画所用图片的高 |
struct Node * |
next |
动画是可以分段的,该节点标识一段动画的相关参数 |
标识数据结构Node
标识:Node
类型:struct Node
含义:标记一段开机动画的相关参数。
Data Type |
Data Item Definition |
Data Item Description |
int |
isPlay |
动画是否播放该子目录,0-不包括,1-不包括 |
int |
maxTime |
该段动画最大运行时间 |
int |
startIndex |
第一个显示的图片 |
int |
endIndex |
最后一个显示的图片 |
char |
type |
图片格式,比如png,jpg;包含BA_IMGFORMAT_MAX_SIZE个字符; |
char |
path |
存放该段动画图片的子目录 |
IDirectFBSurface * |
imgSfc |
BA_IMG_MAX_COUNT个surface描述符,在图片初始化时使用 |
struct Node * |
next |
动画是可以分段的,该节点标识一段动画的相关参数 |
动画组织结构图
框架
代码
/**********************************************
* Author: younger.liucn@hotmail.com
* File name: animation.c
* Description: animation
* Version, Desc
* 1.1 Created
* 1.2 add config
**********************************************/ #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h> #include <time.h>
#include <sys/time.h>
#include <directfb.h> #include "animation.h" /* config information */
#define ANIM_LINE_MAX_SIZE 128
#define ANIM_FILENAME_MAX_SIZE 128
#define ANIM_IMAGE_FORMAT_SIZE 8
#define ANIM_PARTNAME_MAX_SIZE 8
#define ANIM_IMAGES_MAX_COUNT 32
#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_DIR "/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)
/*********************************************************
* log flags and func of debug and error infor.[End]
********************************************************/ /*********************************************************
* Data structure and Global variants [Begin]
********************************************************/
/* 使用directFB画图所需的四个DFB资源 */
struct AnimationDsc {
IDirectFB *dfb;
IDirectFBDisplayLayer *layer;
IDirectFBWindow *window;
IDirectFBSurface *surface;
};
static struct AnimationDsc badsc; /* 定义Animation part */
typedef struct HeadNode{
int fps;
int imgWidth;
int imgHeight;
struct Node *next;
}HeadNode; typedef struct Node{
int isPlay;
int maxTime;
int startIndex;
int endIndex;
char type[ANIM_IMAGE_FORMAT_SIZE];
char path[ANIM_PARTNAME_MAX_SIZE];
IDirectFBSurface *imgSfc[ANIM_IMAGES_MAX_COUNT];
struct Node *next;
}Node; static struct HeadNode head;
/*********************************************************
* Data structure and Global variants [End]
********************************************************/ /*********************************************************
* Some functions help animation [Begin]
********************************************************/
struct HeadNode *listAddNodeT(
struct HeadNode *pheadnode,
struct Node *node)
{
struct Node *L = NULL, *H = NULL;
if(NULL == node) {
ANIM_ERROR("Node is NULL!\n");
}
if (NULL == pheadnode->next) {
pheadnode->next = node;
return pheadnode;
} L = pheadnode->next;
H = L;
while(NULL != L->next) {
L = L->next;
}
L->next = node; pheadnode->next = H;
return pheadnode;
} static void listFreeNode(struct Node *phead)
{
struct Node *L = NULL; L = phead;
while (NULL != phead) {
L = phead->next;
free(phead);
phead = L;
} return ;
} /* 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]
********************************************************/
static int initConfig()
{
int ret = 0;
FILE *fp = NULL;
struct Node *node;
char strline[ANIM_LINE_MAX_SIZE];
char filename[ANIM_FILENAME_MAX_SIZE]; char type[ANIM_IMAGE_FORMAT_SIZE], path[ANIM_PARTNAME_MAX_SIZE];
int run = 0, fps = 0, maxtime = 0;
int startindex = 0, endindex = 0, width = 0, height = 0; head.fps = ANIM_IMG_DEFAULT_FPS;
head.imgWidth= ANIM_IMG_DEFAULT_WIDTH;
head.imgHeight = ANIM_IMG_DEFAULT_HEIGHT;
head.next = NULL;
memset(strline, 0x0, sizeof(strline));
memset(filename, 0x0, sizeof(filename));
snprintf(filename, ANIM_FILENAME_MAX_SIZE, "%s/%s", ANIM_DEFAULT_LOGO_DIR, "animation.cfg");
if(!checkFileExist(filename)) {
ANIM_ERROR("Can't find %s \n",filename);
ret = -1;
goto bail;
} fp = fopen(filename, "r");
if (NULL == fp) {
ANIM_ERROR("Open failed: %s\n", filename);
ret = -1;
goto bail;
} while(!feof(fp)) {
memset(type, 0x0, sizeof(type));
memset(path, 0x0, sizeof(path));
ANIM_DEBUG("Line: %s", strline);
if (sscanf(strline, "%d %d %d", &width, &height, &fps) == 3) {
head.fps = fps;
head.imgWidth = width;
head.imgHeight = height;
ANIM_DEBUG("Animation width: %d,height:%d,fps:%d\n", width, height, fps);
} else if ((sscanf(strline, "%s %d %d %d %d %s",
type, &run, &startindex, &endindex, &maxtime, path) == 6)
&& (0 != run)) {
node = (struct Node *)malloc(sizeof(struct Node));
if (NULL == node) {
ANIM_ERROR("Node malloc failed!\n");
ret = -1;
break;
}
ANIM_DEBUG("==Path:%s,typy:%s,isPlay:%d\n", path, type, run);
ANIM_DEBUG("==start:%d, end:%d, maxtime:%d\n", startindex, endindex, maxtime);
node->isPlay = run;
node->startIndex = startindex;
node->endIndex = endindex;
node->maxTime = maxtime;
strncpy(node->path, path, (strlen(path) + 1) > ANIM_PARTNAME_MAX_SIZE ?
(strlen(path) + 1) : ANIM_PARTNAME_MAX_SIZE);
strncpy(node->type, type, (strlen(type) + 1) > ANIM_IMAGE_FORMAT_SIZE ?
(strlen(type) + 1) : ANIM_IMAGE_FORMAT_SIZE);
node->next = NULL;
listAddNodeT(&head, node);
node = NULL;
}
fgets(strline, ANIM_LINE_MAX_SIZE, fp);
} fclose(fp); bail:
return ret;
}
static void freeConfig()
{
listFreeNode(head.next);
return ;
} 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 ;
} 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;
} /* free images */
static void deinitImages()
{
int i = 0;
struct Node *part = NULL; part = head.next;
while(part) {
for (i = 0; i <= ANIM_IMAGES_MAX_COUNT; i++) {
if (part->imgSfc[i]) {
part->imgSfc[i]->Release(part->imgSfc[i]);
} else {
break;
}
}
part = part->next;
} return ;
} static int initImages()
{
int ret = 0, i = 0;
char filename[ANIM_FILENAME_MAX_SIZE];
IDirectFBSurface *tmp_sfc = NULL; struct Node *part = NULL; part = head.next;
while(part) {
for (i = 0; i < ANIM_IMAGES_MAX_COUNT; i++) {
part->imgSfc[i] = NULL;
} for (i = part->startIndex; i <= part->endIndex; i++) {
tmp_sfc = NULL;
memset(filename, 0x0, sizeof(filename));
snprintf(filename, ANIM_FILENAME_MAX_SIZE, "%s/%s/%d.%s",
ANIM_DEFAULT_LOGO_DIR, part->path, i, part->type);
ret = doLoadImg(filename, &tmp_sfc, NULL, NULL);
if (ret != 0) {
goto bail;
}
part->imgSfc[i - part->startIndex] = tmp_sfc;
}
part = part->next;
} 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 = 0, i = 0;
int width = 0, height = 0;
struct timespec before_draw, after_draw;
unsigned long elapsed_msec = 0, total_msec = 0;
IDirectFBSurface *primary = badsc.surface;
IDirectFBSurface *bg_sfc = NULL;
unsigned long interval = (1000 / head.fps);
struct Node *part = NULL; 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");
part = head.next;
while(part) {
i = part->startIndex;
do {
if(i >= part->endIndex) {
i = 0;
} clock_gettime(CLOCK_MONOTONIC, &before_draw);
fillDFBSurface(primary, part->imgSfc[i],
(width - head.imgWidth) / 2,(height - head.imgHeight) / 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 >= part->maxTime) {
ANIM_NOTICE("Stopped by Timeout(%lu).\n", total_msec);
break;
} i++;
} while(1);
part = part->next;
} 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()
{
int ret = 0; ret = initConfig();
if(ret) {
return ;
} ret = initImages();
if(ret) {
ANIM_ERROR("Init images failed!\n");
goto out;
} doMovie();
deinitImages(); out:
freeConfig();
return ;
} int main(int argc, char **argv)
{
ANIM_NOTICE("Animation entry.\n");
initResources(argc, argv);
doAnimation();
freeResources(); ANIM_NOTICE("Animation exit.\n");
return 0;
}
作者:Younger Liu,
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。
DirectFB 之 分段动画的更多相关文章
- 同时对view延时执行两个动画时候的现象
同时对view延时执行两个动画时候的现象 对于view延时执行了两个动画后,会将第一个动画效果终止了,直接在第一个动画的view的最后的状态上接执行后续的动画效果,也就是说,我们可以利用这个特性来写分 ...
- 动画-CAAnimationGroup(动画组合)
动画-CAAnimationGroup(动画组合) 我们知道IOS可以完成多种类型的动画,但是如果我们想在同一个时间端内同事完成两种或者两种以上的动画组合的时候是不是可以呢?答案是肯定的. 这里我们有 ...
- DirectFB 之 动画播放初步
在基于linux的嵌入式仿真平台开发中,终端的美观和可定制是一个重要的问题.单调的"白纸黑字"型表现方式可谓大煞风景.改造linux控制台使之美观可定制地展示开机信息和logo成为 ...
- android TranslateAnimation 顶部segment分段移动动画
这里实现的功能是从主页布局的fragment点击跳转到一个acitivity,然后顶部是一个切换的segment顶部是一个listview,点击segment分段让listview加载不同的内容.我这 ...
- iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
iOS精选源码 APP启动视频 自定义按钮,图片可调整图文间距SPButton 一款定制性极高的轮播图,可自定义轮播图Item的样式(或只... iOS 筛选菜单 分段选择器 仿微信导航栏的实现,让你 ...
- UISwitch(开关控件)、UISegmentedControl(分段控件)
一.UISwitch 1.初始化 UISwitch *s1 = [[UISwitch alloc]initWithFrame:CGRectMake(50, 170, 100, 200)]; 2.设 ...
- UI:tomcat(说话小程序)、相框动画、UISgmentcontrol、UISwitch
UISegmentedControl 分段控件 //1. UISegmentedControl 分段控件 (就是一个一个的按钮) //分段显示的标题是以一个数组存储的 NSArray * titles ...
- ReactNative学习实践--动画初探之加载动画
学习和实践react已经有一段时间了,在经历了从最初的彷徨到解决痛点时的兴奋,再到不断实践后遭遇问题时的苦闷,确实被这一种新的思维方式和开发模式所折服,react不是万能的,在很多场景下滥用反而会适得 ...
- 利用CSS3实现页面淡入动画特效
利用CSS3动画属性"@keyframes "可实现一些动态特效,具体语法和参数可以网上自行学习.这篇文章主要是实践应用一下这个动画属性,实现页面淡入特效,在火狐24版.chrom ...
随机推荐
- eclipse 中 Servlet 模板代码(其实是代码提示模板)
说的是模板代码,应该说的是提示的模板代码,并不是一新建就会出现模板. 第一步:先建一个Servlet文件,写好自己想要的模板 我的模板如下: 全选并复制,等会要粘贴到Servlet的提示模板中. pa ...
- java学习笔记----运算符
一.算数运算符 特别说明: 加 ,减 ,乘 ,除 与数学运算一致 取余符号看被除数 自加(减)运算:++a,--a;先做自加(自减)运算在做其他运算 a++,a--;先做其他运算在做自加(自减)运算 ...
- python中input()与raw_input()的区别到底是啥?-----marsggbo原创作品为你解答
首先先给出总结:input () = int(raw_input()) 有图有真相!!! 先看看input的例子: 可见用input键入得到int类型的数据,那如果输入一些非int类型的会怎么样呢? ...
- 于普通用户启动UAC问题
在VS中设置UAC级别操作如下: 项目属性-配置属性-连接器-清单文件 1.UAC执行级别: aslnvoker: 权限级别最低,不需要管理员身份. highestAvailable:获取最高权限执行 ...
- openfire当中的Custom Database Integration Guide的配置
openfire官网配置的链接为:Custom Database Integration Guide 按照上面的步骤一步步配置在xml当中,发现始终不起作用,最后在stackoverflow找到的链接 ...
- 记一次解析XML转对象的笔记
项目中调用第三方API,返回格式是XML字符串,需要将XML反序列化为对象,格式如下: <?xml version="1.0"?> <Response xmlns ...
- Ant.SOA微服务框架开源
开源地址:https://github.com/yuzd/AntServiceStack 框架特色0.Service Management(服务治理) 1.CodeGen Contract Fir ...
- 一个关于Python正则表达式的快速使用手册
一直在纠结自己的博客到底应该写一些什么东西,这几天发现自己的正则用的不是很熟练,于是想要写一篇关于正则表达式的博客,目的就是为了让自己以后要用而又不会的时候不至于像无头苍蝇一样到处乱撞. 有些人在碰到 ...
- 20155205 2016-2017-2 《Java程序设计》第4周学习总结
20155205 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 private成员会被继承,只不过子类无法直接存取,必须通过父类提供的方法来存取(若 ...
- XJOIWinterCampPrecontest1-P2队列
2 排队2.1 题目有n 个人打水,第i 个人打水需要ai 的时间.有K 个水龙头,你可以随意安排他们打水的顺序以及使用哪一个水龙头,但是每一时刻每一个水龙头只能有一个人使用且一个人一旦开始打水就不能 ...