blob: 4038724f68649ded19b373c7d2b4d21cb41456b1 [file] [log] [blame]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkCanvas.h"
#include "SkCommandLineFlags.h"
#include "SkGraphics.h"
#include "SkOSFile.h"
#include "SkOSPath.h"
#include "SkStream.h"
#include "SkSurface.h"
#if defined(SK_ENABLE_SKOTTIE)
#include "Skottie.h"
#endif
DEFINE_string2(input, i, nullptr, "Input .json file.");
DEFINE_string2(writePath, w, nullptr, "Output directory. Frames are names [0-9]{6}.png.");
DEFINE_double(t0, 0, "Timeline start [0..1].");
DEFINE_double(t1, 1, "Timeline stop [0..1].");
DEFINE_double(fps, 30, "Decode frames per second.");
DEFINE_int32(width , 800, "Render width.");
DEFINE_int32(height, 600, "Render height.");
int main(int argc, char** argv) {
#if defined(SK_ENABLE_SKOTTIE)
SkCommandLineFlags::Parse(argc, argv);
SkAutoGraphics ag;
if (FLAGS_input.isEmpty() || FLAGS_writePath.isEmpty()) {
SkDebugf("Missing required 'input' and 'writePath' args.\n");
return 1;
}
if (FLAGS_fps <= 0) {
SkDebugf("Invalid fps: %f.\n", FLAGS_fps);
return 1;
}
if (!sk_mkdir(FLAGS_writePath[0])) {
return 1;
}
auto anim = skottie::Animation::MakeFromFile(FLAGS_input[0]);
if (!anim) {
SkDebugf("Could not load animation: '%s'.\n", FLAGS_input[0]);
return 1;
}
auto surface = SkSurface::MakeRasterN32Premul(FLAGS_width, FLAGS_height);
if (!surface) {
SkDebugf("Could not allocate a %d x %d buffer.\n", FLAGS_width, FLAGS_height);
return 1;
}
auto* canvas = surface->getCanvas();
canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(anim->size()),
SkRect::MakeIWH(FLAGS_width, FLAGS_height),
SkMatrix::kCenter_ScaleToFit));
static constexpr double kMaxFrames = 10000;
const auto t0 = SkTPin(FLAGS_t0, 0.0, 1.0),
t1 = SkTPin(FLAGS_t1, t0, 1.0),
advance = 1 / std::min(anim->duration() * FLAGS_fps, kMaxFrames);
size_t frame_index = 0;
for (auto t = t0; t <= t1; t += advance) {
canvas->clear(SK_ColorTRANSPARENT);
anim->seek(t);
anim->render(canvas);
auto png_data = surface->makeImageSnapshot()->encodeToData();
if (!png_data) {
SkDebugf("Failed to encode frame #%lu\n", frame_index);
return 1;
}
const auto frame_file = SkStringPrintf("0%06d.png", frame_index++);
SkFILEWStream wstream(SkOSPath::Join(FLAGS_writePath[0], frame_file.c_str()).c_str());
if (!wstream.isValid()) {
SkDebugf("Could not open '%s/%s' for writing.\n",
FLAGS_writePath[0], frame_file.c_str());
return 1;
}
wstream.write(png_data->data(), png_data->size());
}
#else
SkDebugf("This tool requires Skottie support.\n");
#endif
return 0;
}