Skip to content

Instantly share code, notes, and snippets.

@SneakyWhoami
Last active November 12, 2021 10:54
Show Gist options
  • Save SneakyWhoami/79c553f66502e2369d3673095585a3f5 to your computer and use it in GitHub Desktop.
Save SneakyWhoami/79c553f66502e2369d3673095585a3f5 to your computer and use it in GitHub Desktop.
lottie thumbnailer
cmake_minimum_required(VERSION 3.0)
project(lottiethumb)
list(APPEND CMAKE_PREFIX_PATH "/usr/share/quazip")
set(CMAKE_CXX_STANDARD 14)
find_package(rlottie REQUIRED)
find_package(Qt5 COMPONENTS Gui REQUIRED)
find_package(QuaZip5 REQUIRED)
include_directories(${QUAZIP_INCLUDE_DIRS})
add_executable(lottiethumb main.cpp)
target_link_libraries(lottiethumb rlottie Qt5::Gui ${QUAZIP_LIBRARIES})
#include <iostream>
#include <rlottie.h>
#include <QImage>
#include <quagzipfile.h>
#include <QDebug>
#include <cmath>
int main(int argc, char **argv)
{
// help text stuff start
// if you delete this test, you can hardcode default in/out filenames
if (argc < 3) {
std::cout << "Usage: " << argv[0] << "<infilename.json> <outfilename.webp> [width] [height] [percentage]\n"
<< "Create a thumbnail for infilename.json at outfilename.webp, of size [width] pixels by [height] pixels.\n"
<< "Optionally, create the thumbnail on the frame at the [percentage] playback progress mark.\n"
<< "Output file format is determined by output filename and installed QImageCodecs.\n";
exit(2);
}
// help text stuff end, defaults start
QString inName = argc > 1 ? argv[1] : "/tmp/AnimatedSticker.tgs";
QString outName = argc > 2 ? argv[2] : "/tmp/stick.webp";
int width = argc > 3 ? atoi(argv[3]) : 512;
width = width > 0 ? width : 512;
int height = argc > 4 ? atoi(argv[4]) : 512;
height = height > 0 ? height : 512;
double selected = argc > 5 ? atoi(argv[5]) : 80;
selected = fmod(selected, 100);
selected = selected > 0 ? selected : 80;
selected = 100 / selected;
// defaults end, business logic start
QuaGzipFile lottiefile(inName);
lottiefile.open(QIODevice::ReadOnly);
// This format is the default used by rlottie anyway
QImage pic(width, height, QImage::Format_ARGB32_Premultiplied);
// rlottie can render to a surface if it looks liek this
auto buffer = std::make_unique<uint32_t[]>(width * height);
// so we load the animation (the input file)
auto animation = rlottie::Animation::loadFromData(lottiefile.readAll().toStdString(), inName.toStdString());
// then we load up our frame from the animation into buffer...
rlottie::Surface surface(buffer.get(), width, height, width * 4);
animation->renderSync((animation->totalFrame() / selected), surface);
// give it a gentle massage to get it into QImage
for (int i = 0; i < width * height; i++) {
if (buffer.get()[i]) {
pic.setPixelColor(i % width, i / height, QColor(buffer.get()[i]));
} else {
// an int value of straight-up "0" is our transparent (background) colour
pic.setPixelColor(i % width, i / height, QColor(0, 0, 0, 0));
}
}
// Qt will magically spit out whatever image format is implied by the file extension
if (pic.save(outName)) {
return 0;
} else {
return 1;
}
}
@SneakyWhoami
Copy link
Author

Very crashable :) I don't check for sanity on any of the files going in (right now) so you can pass in a malformed file and get a segfault. Just heads-up in case I don't come back and fix it up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment