Attach PPI pixels to documents

This commit is contained in:
2026-06-01 13:43:27 +02:00
parent 88507df90e
commit ad255a6ddf
14 changed files with 569 additions and 104 deletions

View File

@@ -2,6 +2,7 @@
#include "assets/image_metadata.h"
#include "assets/ppi_header.h"
#include "document/document.h"
#include "document/ppi_import.h"
#include "foundation/parse.h"
#include "foundation/result.h"
#include "paint/stroke.h"
@@ -405,79 +406,6 @@ int inspect_project(int argc, char** argv)
return 0;
}
pp::foundation::Result<pp::paint::BlendMode> ppi_layer_blend_mode(std::uint32_t blend_mode) noexcept
{
switch (blend_mode) {
case 0:
return pp::foundation::Result<pp::paint::BlendMode>::success(pp::paint::BlendMode::normal);
case 1:
return pp::foundation::Result<pp::paint::BlendMode>::success(pp::paint::BlendMode::multiply);
case 2:
return pp::foundation::Result<pp::paint::BlendMode>::success(pp::paint::BlendMode::screen);
case 3:
return pp::foundation::Result<pp::paint::BlendMode>::success(pp::paint::BlendMode::color_dodge);
case 4:
return pp::foundation::Result<pp::paint::BlendMode>::success(pp::paint::BlendMode::overlay);
default:
return pp::foundation::Result<pp::paint::BlendMode>::failure(
pp::foundation::Status::invalid_argument("PPI layer blend mode is not supported by pp_document"));
}
}
pp::foundation::Result<pp::document::CanvasDocument> document_from_ppi_index(
const pp::assets::PpiProjectIndex& project)
{
if (project.body.layers.empty()) {
return pp::foundation::Result<pp::document::CanvasDocument>::failure(
pp::foundation::Status::invalid_argument("PPI project has no layers"));
}
const auto& reference_frames = project.body.layers.front().frames;
if (reference_frames.empty()) {
return pp::foundation::Result<pp::document::CanvasDocument>::failure(
pp::foundation::Status::invalid_argument("PPI project has no frames"));
}
std::vector<pp::document::AnimationFrame> frames;
frames.reserve(reference_frames.size());
for (const auto& frame : reference_frames) {
frames.push_back(pp::document::AnimationFrame { .duration_ms = frame.duration_ms });
}
std::vector<std::vector<pp::document::AnimationFrame>> layer_frames;
layer_frames.reserve(project.body.layers.size());
std::vector<pp::document::DocumentLayerConfig> layers;
layers.reserve(project.body.layers.size());
for (const auto& layer : project.body.layers) {
const auto blend_mode = ppi_layer_blend_mode(layer.blend_mode);
if (!blend_mode) {
return pp::foundation::Result<pp::document::CanvasDocument>::failure(blend_mode.status());
}
auto& frame_list = layer_frames.emplace_back();
frame_list.reserve(layer.frames.size());
for (const auto& frame : layer.frames) {
frame_list.push_back(pp::document::AnimationFrame { .duration_ms = frame.duration_ms });
}
layers.push_back(pp::document::DocumentLayerConfig {
.name = layer.name,
.visible = layer.visible,
.alpha_locked = layer.alpha_locked,
.opacity = layer.opacity,
.blend_mode = blend_mode.value(),
.frames = std::span<const pp::document::AnimationFrame>(frame_list.data(), frame_list.size()),
});
}
return pp::document::CanvasDocument::create_from_snapshot(pp::document::DocumentSnapshotConfig {
.width = project.body.summary.width,
.height = project.body.summary.height,
.layers = layers,
.frames = frames,
});
}
int load_project(int argc, char** argv)
{
InspectProjectArgs args;
@@ -498,13 +426,13 @@ int load_project(int argc, char** argv)
std::istreambuf_iterator<char>()
};
const auto* data = reinterpret_cast<const std::byte*>(chars.data());
const auto project = pp::assets::parse_ppi_project_index(std::span<const std::byte>(data, chars.size()));
const auto project = pp::assets::decode_ppi_project_images(std::span<const std::byte>(data, chars.size()));
if (!project) {
print_error("load-project", project.status().message);
return 2;
}
const auto document_result = document_from_ppi_index(project.value());
const auto document_result = pp::document::import_ppi_project_document(project.value());
if (!document_result) {
print_error("load-project", document_result.status().message);
return 2;
@@ -513,7 +441,8 @@ int load_project(int argc, char** argv)
const auto& document = document_result.value();
std::cout << "{\"ok\":true,\"command\":\"load-project\""
<< ",\"source\":\"ppi\""
<< ",\"pixelDataLoaded\":false"
<< ",\"pixelDataLoaded\":" << (document.face_pixel_payload_count() > 0U ? "true" : "false")
<< ",\"facePayloads\":" << document.face_pixel_payload_count()
<< ",\"document\":{\"width\":" << document.width()
<< ",\"height\":" << document.height()
<< ",\"layers\":" << document.layers().size()