#include "lottieicon.h" #include #include #include 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 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; }