lottie2gif.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "gif.h"
  2. #include <rlottie.h>
  3. #include<iostream>
  4. #include<string>
  5. #include<vector>
  6. #include<array>
  7. #ifndef _WIN32
  8. #include<libgen.h>
  9. #else
  10. #include <windows.h>
  11. #include <stdlib.h>
  12. #endif
  13. class GifBuilder {
  14. public:
  15. explicit GifBuilder(const std::string &fileName , const uint32_t width,
  16. const uint32_t height, const int bgColor=0xffffffff, const uint32_t delay = 2)
  17. {
  18. GifBegin(&handle, fileName.c_str(), width, height, delay);
  19. bgColorR = (uint8_t) ((bgColor & 0xff0000) >> 16);
  20. bgColorG = (uint8_t) ((bgColor & 0x00ff00) >> 8);
  21. bgColorB = (uint8_t) ((bgColor & 0x0000ff));
  22. }
  23. ~GifBuilder()
  24. {
  25. GifEnd(&handle);
  26. }
  27. void addFrame(rlottie::Surface &s, uint32_t delay = 2)
  28. {
  29. argbTorgba(s);
  30. GifWriteFrame(&handle,
  31. reinterpret_cast<uint8_t *>(s.buffer()),
  32. s.width(),
  33. s.height(),
  34. delay);
  35. }
  36. void argbTorgba(rlottie::Surface &s)
  37. {
  38. uint8_t *buffer = reinterpret_cast<uint8_t *>(s.buffer());
  39. uint32_t totalBytes = s.height() * s.bytesPerLine();
  40. for (uint32_t i = 0; i < totalBytes; i += 4) {
  41. unsigned char a = buffer[i+3];
  42. // compute only if alpha is non zero
  43. if (a) {
  44. unsigned char r = buffer[i+2];
  45. unsigned char g = buffer[i+1];
  46. unsigned char b = buffer[i];
  47. if (a != 255) { //un premultiply
  48. unsigned char r2 = (unsigned char) ((float) bgColorR * ((float) (255 - a) / 255));
  49. unsigned char g2 = (unsigned char) ((float) bgColorG * ((float) (255 - a) / 255));
  50. unsigned char b2 = (unsigned char) ((float) bgColorB * ((float) (255 - a) / 255));
  51. buffer[i] = r + r2;
  52. buffer[i+1] = g + g2;
  53. buffer[i+2] = b + b2;
  54. } else {
  55. // only swizzle r and b
  56. buffer[i] = r;
  57. buffer[i+2] = b;
  58. }
  59. } else {
  60. buffer[i+2] = bgColorB;
  61. buffer[i+1] = bgColorG;
  62. buffer[i] = bgColorR;
  63. }
  64. }
  65. }
  66. private:
  67. GifWriter handle;
  68. uint8_t bgColorR, bgColorG, bgColorB;
  69. };
  70. class App {
  71. public:
  72. int render(uint32_t w, uint32_t h)
  73. {
  74. auto player = rlottie::Animation::loadFromFile(fileName);
  75. if (!player) return help();
  76. auto buffer = std::unique_ptr<uint32_t[]>(new uint32_t[w * h]);
  77. size_t frameCount = player->totalFrame();
  78. GifBuilder builder(gifName.data(), w, h, bgColor);
  79. for (size_t i = 0; i < frameCount ; i++) {
  80. rlottie::Surface surface(buffer.get(), w, h, w * 4);
  81. player->renderSync(i, surface);
  82. builder.addFrame(surface);
  83. }
  84. return result();
  85. }
  86. int setup(int argc, char **argv)
  87. {
  88. char *path{nullptr};
  89. if (argc > 1) path = argv[1];
  90. if (argc > 2) bgColor = strtol(argv[2], NULL, 16);
  91. if (!path) return help();
  92. std::array<char, 5000> memory;
  93. #ifdef _WIN32
  94. path = _fullpath(memory.data(), path, memory.size());
  95. #else
  96. path = realpath(path, memory.data());
  97. #endif
  98. if (!path) return help();
  99. fileName = std::string(path);
  100. if (!jsonFile()) return help();
  101. gifName = basename(fileName);
  102. gifName.append(".gif");
  103. return 0;
  104. }
  105. private:
  106. std::string basename(const std::string &str)
  107. {
  108. return str.substr(str.find_last_of("/\\") + 1);
  109. }
  110. bool jsonFile() {
  111. std::string extn = ".json";
  112. if ( fileName.size() <= extn.size() ||
  113. fileName.substr(fileName.size()- extn.size()) != extn )
  114. return false;
  115. return true;
  116. }
  117. int result() {
  118. std::cout<<"Generated GIF file : "<<gifName<<std::endl;
  119. return 0;
  120. }
  121. int help() {
  122. std::cout<<"Usage: \n lottie2gif [lottieFileName] [bgColor]\n\nExamples: \n $ lottie2gif input.json\n $ lottie2gif input.json ff00ff\n\n";
  123. return 1;
  124. }
  125. private:
  126. int bgColor = 0xffffffff;
  127. std::string fileName;
  128. std::string gifName;
  129. };
  130. int
  131. main(int argc, char **argv)
  132. {
  133. App app;
  134. if (app.setup(argc, argv)) return 1;
  135. app.render(200, 200);
  136. return 0;
  137. }