Export equirectangular JPEGs through paint renderer
This commit is contained in:
@@ -38,6 +38,40 @@ bool is_png_export_target(std::string_view path) noexcept
|
||||
&& (extension[3] == 'g' || extension[3] == 'G');
|
||||
}
|
||||
|
||||
bool ascii_iequals(std::string_view left, std::string_view right) noexcept
|
||||
{
|
||||
if (left.size() != right.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < left.size(); ++i) {
|
||||
auto lhs = left[i];
|
||||
if (lhs >= 'A' && lhs <= 'Z') {
|
||||
lhs = static_cast<char>(lhs - 'A' + 'a');
|
||||
}
|
||||
auto rhs = right[i];
|
||||
if (rhs >= 'A' && rhs <= 'Z') {
|
||||
rhs = static_cast<char>(rhs - 'A' + 'a');
|
||||
}
|
||||
if (lhs != rhs) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_extension(std::string_view path, std::string_view extension) noexcept
|
||||
{
|
||||
return path.size() >= extension.size()
|
||||
&& ascii_iequals(path.substr(path.size() - extension.size()), extension);
|
||||
}
|
||||
|
||||
bool is_jpeg_export_target(std::string_view path) noexcept
|
||||
{
|
||||
return has_extension(path, ".jpg") || has_extension(path, ".jpeg");
|
||||
}
|
||||
|
||||
struct LegacyDocumentExportSnapshotReports {
|
||||
pp::app::DocumentCanvasSnapshotResult snapshot;
|
||||
pp::paint_renderer::DocumentFrameFacePngExportResult face_pngs;
|
||||
@@ -270,32 +304,52 @@ pp::foundation::Status export_animation_frames_from_document_snapshot(
|
||||
return pp::app::execute_document_export_collection_write(target, payloads, services);
|
||||
}
|
||||
|
||||
pp::foundation::Status export_equirectangular_png_from_document_snapshot(
|
||||
pp::foundation::Status export_equirectangular_from_document_snapshot(
|
||||
App& app,
|
||||
const pp::app::DocumentExportFileTarget& target,
|
||||
const LegacyDocumentExportSnapshotReports& reports)
|
||||
{
|
||||
if (!is_png_export_target(target.path)) {
|
||||
std::span<const std::byte> bytes;
|
||||
pp::paint_renderer::DocumentFrameEquirectangularPngExportResult png_export;
|
||||
pp::paint_renderer::DocumentFrameEquirectangularJpegExportResult jpeg_export;
|
||||
|
||||
if (is_png_export_target(target.path)) {
|
||||
auto exported = pp::paint_renderer::export_document_frame_equirectangular_png(reports.face_pngs.composite);
|
||||
if (!exported) {
|
||||
return exported.status();
|
||||
}
|
||||
|
||||
png_export = std::move(exported.value());
|
||||
LOG(
|
||||
"export-equirectangular document export PNG writer: %ux%u bytes=%llu facePayloads=%zu compositedLayerFaces=%zu",
|
||||
png_export.equirectangular_extent.width,
|
||||
png_export.equirectangular_extent.height,
|
||||
static_cast<unsigned long long>(png_export.encoded_bytes),
|
||||
png_export.face_payload_count,
|
||||
png_export.composited_layer_face_count);
|
||||
bytes = std::span<const std::byte>(png_export.png.data(), png_export.png.size());
|
||||
} else if (is_jpeg_export_target(target.path)) {
|
||||
auto exported = pp::paint_renderer::export_document_frame_equirectangular_jpeg(reports.face_pngs.composite);
|
||||
if (!exported) {
|
||||
return exported.status();
|
||||
}
|
||||
|
||||
jpeg_export = std::move(exported.value());
|
||||
LOG(
|
||||
"export-equirectangular document export JPEG writer: %ux%u bytes=%llu facePayloads=%zu compositedLayerFaces=%zu xmp=%s",
|
||||
jpeg_export.equirectangular_extent.width,
|
||||
jpeg_export.equirectangular_extent.height,
|
||||
static_cast<unsigned long long>(jpeg_export.encoded_bytes),
|
||||
jpeg_export.face_payload_count,
|
||||
jpeg_export.composited_layer_face_count,
|
||||
jpeg_export.xmp_injected ? "true" : "false");
|
||||
bytes = std::span<const std::byte>(jpeg_export.jpeg.data(), jpeg_export.jpeg.size());
|
||||
} else {
|
||||
return pp::foundation::Status::invalid_argument(
|
||||
"document snapshot equirectangular export currently supports PNG targets only");
|
||||
"document snapshot equirectangular export currently supports PNG and JPEG targets only");
|
||||
}
|
||||
|
||||
auto exported = pp::paint_renderer::export_document_frame_equirectangular_png(reports.face_pngs.composite);
|
||||
if (!exported) {
|
||||
return exported.status();
|
||||
}
|
||||
|
||||
auto exported_value = std::move(exported.value());
|
||||
LOG(
|
||||
"export-equirectangular document export PNG writer: %ux%u bytes=%llu facePayloads=%zu compositedLayerFaces=%zu",
|
||||
exported_value.equirectangular_extent.width,
|
||||
exported_value.equirectangular_extent.height,
|
||||
static_cast<unsigned long long>(exported_value.encoded_bytes),
|
||||
exported_value.face_payload_count,
|
||||
exported_value.composited_layer_face_count);
|
||||
const auto write_status = write_export_binary_file(
|
||||
target.path,
|
||||
std::span<const std::byte>(exported_value.png.data(), exported_value.png.size()));
|
||||
const auto write_status = write_export_binary_file(target.path, bytes);
|
||||
if (!write_status.ok()) {
|
||||
return write_status;
|
||||
}
|
||||
@@ -320,10 +374,10 @@ public:
|
||||
{
|
||||
auto* app = &app_;
|
||||
#if !__WEB__
|
||||
if (is_png_export_target(target.path)) {
|
||||
if (is_png_export_target(target.path) || is_jpeg_export_target(target.path)) {
|
||||
const auto prepared = prepare_legacy_document_export_snapshot(app_, "export-equirectangular");
|
||||
if (prepared) {
|
||||
const auto exported = export_equirectangular_png_from_document_snapshot(app_, target, prepared.value());
|
||||
const auto exported = export_equirectangular_from_document_snapshot(app_, target, prepared.value());
|
||||
if (exported.ok()) {
|
||||
show_export_success_dialog(
|
||||
app_,
|
||||
|
||||
Reference in New Issue
Block a user