You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.3 KiB
72 lines
2.3 KiB
#include "lottieicon.h" |
|
#include <rlottie_capi.h> |
|
#include <zlib.h> |
|
#include <cstring> |
|
|
|
static QByteArray unpackGzip(const QByteArray &data) { |
|
if (data.isEmpty()) return {}; |
|
z_stream strm = {}; |
|
int ret = inflateInit2(&strm, 16 + MAX_WBITS); |
|
if (ret != Z_OK) return {}; |
|
strm.avail_in = (uInt)data.size(); |
|
strm.next_in = (Bytef *)data.constData(); |
|
QByteArray result; |
|
result.resize(data.size() * 3); |
|
size_t total = 0; |
|
do { |
|
size_t remain = (size_t)result.size() - total; |
|
if (remain < 4096) { |
|
result.resize(result.size() * 2); |
|
remain = (size_t)result.size() - total; |
|
} |
|
strm.avail_out = (uInt)remain; |
|
strm.next_out = (Bytef *)result.data() + total; |
|
ret = inflate(&strm, Z_NO_FLUSH); |
|
if (ret == Z_STREAM_ERROR || ret == Z_DATA_ERROR) { |
|
inflateEnd(&strm); |
|
return {}; |
|
} |
|
total += remain - strm.avail_out; |
|
} while (ret != Z_STREAM_END); |
|
inflateEnd(&strm); |
|
result.resize((int)total); |
|
return result; |
|
} |
|
|
|
LottieIcon::LottieIcon(const QByteArray &tgsData) { |
|
QByteArray json = unpackGzip(tgsData); |
|
if (json.isEmpty()) return; |
|
|
|
m_jsonData = json; |
|
m_anim = lottie_animation_from_data(m_jsonData.constData(), "", ""); |
|
if (!m_anim) return; |
|
|
|
lottie_animation_get_size(m_anim, &m_w, &m_h); |
|
m_totalFrames = (int)lottie_animation_get_totalframe(m_anim); |
|
m_frameRate = lottie_animation_get_framerate(m_anim); |
|
if (m_totalFrames <= 0) m_totalFrames = 1; |
|
m_valid = true; |
|
} |
|
|
|
LottieIcon::~LottieIcon() { |
|
if (m_anim) lottie_animation_destroy(m_anim); |
|
} |
|
|
|
QImage LottieIcon::renderFrame(int frameNum, QSize targetSize) const { |
|
if (!m_valid || targetSize.width() <= 0 || targetSize.height() <= 0) |
|
return QImage(); |
|
|
|
int w = targetSize.width(); |
|
int h = targetSize.height(); |
|
size_t stride = (size_t)w * 4; |
|
std::vector<uint32_t> buffer((size_t)w * (size_t)h); |
|
|
|
int frame = frameNum % m_totalFrames; |
|
lottie_animation_render(m_anim, (size_t)frame, buffer.data(), |
|
(size_t)w, (size_t)h, stride); |
|
|
|
QImage img(w, h, QImage::Format_ARGB32_Premultiplied); |
|
for (int y = 0; y < h; y++) |
|
std::memcpy(img.scanLine(y), &buffer[(size_t)y * (size_t)w], stride); |
|
return img; |
|
}
|
|
|