[skottie] Add a tool for dumping encoded animation frames
Exports animation frames as a sequence of .png files: 0000000.png 0000001.png ... Usage: skottie_tool -i <input_json> -w <out_dir> Other options: --width Frame width (default: 800) --height Frame height (default: 600) --fps Frames per second (default: 30) --t0 Normalized timeline start (default: 0) --t1 Normalized timeline end (default: 1) Change-Id: I4a79be0f823da15e6863909b6d67d38aa74bb740 Reviewed-on: https://skia-review.googlesource.com/132265 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
7d43296341
commit
79725d3271
8
BUILD.gn
8
BUILD.gn
@ -1514,6 +1514,14 @@ if (skia_enable_tools) {
|
||||
]
|
||||
}
|
||||
|
||||
if (is_linux || is_mac || is_win) {
|
||||
test_app("skottie_tool") {
|
||||
deps = [
|
||||
"modules/skottie:tool",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (target_cpu != "wasm") {
|
||||
import("gn/samples.gni")
|
||||
test_lib("samples") {
|
||||
|
@ -58,3 +58,21 @@ source_set("fuzz") {
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
source_set("tool") {
|
||||
testonly = true
|
||||
|
||||
configs += [ "../..:skia_private" ]
|
||||
sources = [
|
||||
"src/SkottieTool.cpp",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"../..:flags",
|
||||
"../..:skia",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":skottie",
|
||||
]
|
||||
}
|
||||
|
100
modules/skottie/src/SkottieTool.cpp
Normal file
100
modules/skottie/src/SkottieTool.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user