zoukankan      html  css  js  c++  java
  • 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!
    ");
        }
        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 
    ",filename);
            ret = -1;
            goto  bail;
        }
    
        fp = fopen(filename, "r");
        if (NULL == fp) {
            ANIM_ERROR("Open failed: %s
    ", 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  %d,height:%d,fps:%d
    ", 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!
    ");
                    ret = -1;
                    break;
                }
                ANIM_DEBUG("==Path:%s,typy:%s,isPlay:%d
    ", path, type, run);
                ANIM_DEBUG("==start:%d, end:%d, maxtime:%d
    ", 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
    ");
            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!
    ", ANIM_LAYERID_USING);
            goto fail;
        } else {
            ANIM_DEBUG("Get layer(%d) independently.
    ", 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!
    ");
            goto fail;
        }
    
    	/* 设置透明度 */
        ret = badsc.window->SetOpacity(badsc.window, 0xFF);
        if(ret != (DFBResult)DFB_OK) {
            ANIM_ERROR("SetOpacity failed!
    ");
            goto fail;
        }
    
        /* 获取window的surface. */
        ret = badsc.window->GetSurface(badsc.window, &(badsc.surface));
        if(ret != (DFBResult)DFB_OK) {
            ANIM_ERROR("SetOpacity failed!
    ");
            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.
    ", -EINVAL);
            return -EINVAL;
        }
    
        ANIM_DEBUG("doLoadImg() entry:%s .
    ", filename);
        if(!checkFileExist(filename)) {
            ANIM_ERROR("file %s does not exist.
    ", filename);
            return -EINVAL;
        }
    
        /* 将要显示的图片及其相关信息保存在一个image provider中 */
        ret = dfb->CreateImageProvider(dfb, filename, &provider);
        if(ret) {
            ANIM_ERROR("CreateImageProvider() for %s failed %d.
    ", filename, ret);
            return ret;
        }
    
        /* 将保存在provider中的图片信息提取出来,存于surface description中 */
        ret = provider->GetSurfaceDescription(provider, &img_dsc);
        if(ret) {
            ANIM_ERROR("GetSurfaceDescription() for %s failed %d.
    ",
                    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.
    ", filename, ret);
            provider->Release(provider);
            return ret;
        }
    
        /* 将图片呈递给刚才建立的logo平面,如果大小不一致,则进行缩放 */
        ret = provider->RenderTo(provider, *surface, NULL);
        if(ret) {
            ANIM_ERROR("RenderTo() for %s failed %d.
    ", 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.
    ");
        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 ...
    ");
        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 
    ",
    				elapsed_msec < interval ? interval : elapsed_msec);
    
    			if(total_msec >= part->maxTime) {
    				ANIM_NOTICE("Stopped by Timeout(%lu).
    ", 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...
    ");
    
        return ;
    }
    
    static void doAnimation()
    {
    	int ret = 0;
    	
    	ret = initConfig();
    	if(ret) {
            return ;
    	}
    
    	ret = initImages();
    	if(ret) {
            ANIM_ERROR("Init images failed!
    ");
            goto out;
    	}
    
        doMovie();
        deinitImages();
    
    out:
        freeConfig();
        return ;
    }
    
    int main(int argc, char **argv)
    {
        ANIM_NOTICE("Animation entry.
    ");
        initResources(argc, argv);
        doAnimation();
        freeResources();
    
        ANIM_NOTICE("Animation exit.
    ");
        return 0;
    }


    作者:Younger Liu,

    本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。


  • 相关阅读:
    java 21
    maven POM.xml 标签详解
    shell sed 替代1
    lua的table库中的常用函数总结
    Lua字符串及模式匹配
    lua文件读写
    qt添加lua支持
    关于c调用lua 对‘luaL_newstate()’未定义的引用的问题解决办法
    Lua开发环境
    linux安装lua相关编译报错
  • 原文地址:https://www.cnblogs.com/youngerchina/p/5624449.html
Copyright © 2011-2022 走看看