added lottie2gif converter for both cmake and meson build
[platform/core/uifw/lottie-player.git] / example / lottie2gif.cpp
1 #include "gif.h"
2 #include "rlottie.h"
3
4 #include<iostream>
5 #include<vector>
6 #include<array>
7 #include<cstdlib>
8
9 class GifBuilder {
10 public:
11     GifBuilder(const std::string &fileName , const uint32_t width,
12                const uint32_t height, const uint32_t delay = 2)
13     {
14         GifBegin(&handle, fileName.c_str(), width, height, delay);
15     }
16     void addFrame(rlottie::Surface &s, uint32_t delay = 2)
17     {
18         argbTorgba(s);
19         GifWriteFrame(&handle,
20                       reinterpret_cast<uint8_t *>(s.buffer()),
21                       s.width(),
22                       s.height(),
23                       delay);
24     }
25     void argbTorgba(rlottie::Surface &s)
26     {
27         uint8_t *buffer = reinterpret_cast<uint8_t *>(s.buffer());
28         uint32_t totalBytes = s.height() * s.bytesPerLine();
29
30         for (uint32_t i = 0; i < totalBytes; i += 4) {
31            unsigned char a = buffer[i+3];
32            // compute only if alpha is non zero
33            if (a) {
34                unsigned char r = buffer[i+2];
35                unsigned char g = buffer[i+1];
36                unsigned char b = buffer[i];
37
38                if (a != 255) { //un premultiply
39                   r = (r * 255) / a;
40                   g = (g * 255) / a;
41                   b = (b * 255) / a;
42
43                   buffer[i] = r;
44                   buffer[i+1] = g;
45                   buffer[i+2] = b;
46
47                } else {
48                  // only swizzle r and b
49                  buffer[i] = r;
50                  buffer[i+2] = b;
51                }
52            } else {
53                buffer[i+2] = 255;
54                buffer[i+1] = 255;
55                buffer[i] = 255;
56            }
57         }
58     }
59     void commit()
60     {
61         GifEnd(&handle);
62     }
63 private:
64     GifWriter      handle;
65 };
66
67 class App {
68 public:
69     int render(uint32_t w, uint32_t h)
70     {
71         auto player = rlottie::Animation::loadFromFile(fileName);
72         if (!player) return help();
73
74         uint32_t* buffer = (uint32_t *) malloc(w * h * 4);
75         size_t frameCount = player->totalFrame();
76
77         GifBuilder builder(baseName.data(), w, h);
78         for (size_t i = 0; i < frameCount ; i++) {
79             rlottie::Surface surface(buffer, w, h, w * 4);
80             player->renderSync(i, surface);
81             builder.addFrame(surface);
82         }
83         builder.commit();
84
85         free(buffer);
86         return result();
87     }
88
89     int setup(int argc, char **argv)
90     {
91         if (argc > 1) fileName = argv[1];
92
93         if (!fileName) return help();
94
95         fileName = realpath(fileName, absoloutePath.data());
96
97         if (!fileName || !jsonFile(fileName) ) return help();
98
99         baseName = absoloutePath;
100         char *base = basename(baseName.data());
101         snprintf(baseName.data(), baseName.size(), "%s.gif",base);
102         return 0;
103     }
104
105 private:
106
107     bool jsonFile(const char *filename) {
108       const char *dot = strrchr(filename, '.');
109       if(!dot || dot == filename) return false;
110       return !strcmp(dot + 1, "json");
111     }
112
113     int result() {
114         std::cout<<"Generated GIF file : "<<baseName.data()<<std::endl;
115         return 0;
116     }
117
118     int help() {
119         std::cout<<"Usage: \n   lottie2gif [lottieFileName]\n";
120         return 1;
121     }
122
123 private:
124     char *fileName{nullptr};
125     std::array<char, 5000> absoloutePath;
126     std::array<char, 5000> baseName;
127 };
128
129 int
130 main(int argc, char **argv)
131 {
132     App app;
133
134     if (app.setup(argc, argv)) return 1;
135
136     app.render(200, 200);
137
138     return 0;
139 }