From dba0bee76cd48d8f99dced07e4b76c9c88e7e0e8 Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 7 Apr 2024 16:34:49 -0400 Subject: [PATCH 1/2] gltfpack: Consolidate image error reporting Instead of printing to stderr manually whenever we have a case when an image can't be saved, call writeImageError; this unifies the error reporting and allows us to produce JSON content that indicates an error. --- gltf/gltfpack.cpp | 4 ++-- gltf/gltfpack.h | 3 ++- gltf/write.cpp | 19 +++++++++++++------ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/gltf/gltfpack.cpp b/gltf/gltfpack.cpp index b20103d3b..48a073457 100644 --- a/gltf/gltfpack.cpp +++ b/gltf/gltfpack.cpp @@ -480,9 +480,9 @@ static void process(cgltf_data* data, const char* input_path, const char* output if (encoded_images.size() && !encoded_images[i].empty()) { if (encoded_images[i].compare(0, 5, "error") == 0) - fprintf(stderr, "Warning: unable to encode image %d (%s), skipping (%s)\n", int(i), image.uri ? image.uri : "?", encoded_images[i].c_str()); + writeImageError(json_images, "encode", int(i), image.uri, encoded_images[i].c_str()); else - writeEncodedImage(json_images, views, image, encoded_images[i], images[i], output_path, settings); + writeEncodedImage(json_images, views, image, encoded_images[i], images[i], i, output_path, settings); encoded_images[i] = std::string(); // reclaim memory early } diff --git a/gltf/gltfpack.h b/gltf/gltfpack.h index 0a2bdf84e..e22608466 100644 --- a/gltf/gltfpack.h +++ b/gltf/gltfpack.h @@ -369,7 +369,8 @@ void writeMaterial(std::string& json, const cgltf_data* data, const cgltf_materi void writeBufferView(std::string& json, BufferView::Kind kind, StreamFormat::Filter filter, size_t count, size_t stride, size_t bin_offset, size_t bin_size, BufferView::Compression compression, size_t compressed_offset, size_t compressed_size); void writeSampler(std::string& json, const cgltf_sampler& sampler); void writeImage(std::string& json, std::vector& views, const cgltf_image& image, const ImageInfo& info, size_t index, const char* input_path, const char* output_path, const Settings& settings); -void writeEncodedImage(std::string& json, std::vector& views, const cgltf_image& image, const std::string& encoded, const ImageInfo& info, const char* output_path, const Settings& settings); +void writeImageError(std::string& json, const char* action, size_t index, const char* uri, const char* reason = NULL); +void writeEncodedImage(std::string& json, std::vector& views, const cgltf_image& image, const std::string& encoded, const ImageInfo& info, size_t index, const char* output_path, const Settings& settings); void writeTexture(std::string& json, const cgltf_texture& texture, const ImageInfo* info, cgltf_data* data, const Settings& settings); void writeMeshAttributes(std::string& json, std::vector& views, std::string& json_accessors, size_t& accr_offset, const Mesh& mesh, int target, const QuantizationPosition& qp, const QuantizationTexture& qt, const Settings& settings); size_t writeMeshIndices(std::vector& views, std::string& json_accessors, size_t& accr_offset, const Mesh& mesh, const Settings& settings); diff --git a/gltf/write.cpp b/gltf/write.cpp index 413c96ece..7eae0d6c8 100644 --- a/gltf/write.cpp +++ b/gltf/write.cpp @@ -896,7 +896,7 @@ void writeSampler(std::string& json, const cgltf_sampler& sampler) } } -static void writeImageData(std::string& json, std::vector& views, const char* uri, const char* mime_type, const std::string& contents, const char* output_path, TextureKind kind, bool embed) +static void writeImageData(std::string& json, std::vector& views, size_t index, const char* uri, const char* mime_type, const std::string& contents, const char* output_path, TextureKind kind, bool embed) { bool dataUri = uri && strncmp(uri, "data:", 5) == 0; @@ -913,7 +913,7 @@ static void writeImageData(std::string& json, std::vector& views, co } else { - fprintf(stderr, "Warning: unable to save image %s to %s, skipping\n", uri, file_path.c_str()); + writeImageError(json, "save", int(index), uri, file_path.c_str()); } } else @@ -939,16 +939,23 @@ void writeImage(std::string& json, std::vector& views, const cgltf_i std::string mime_type; if (!readImage(image, input_path, img_data, mime_type)) { - fprintf(stderr, "Warning: unable to read image %d (%s), skipping\n", int(index), image.uri ? image.uri : "?"); + writeImageError(json, "read", index, image.uri); return; } - writeImageData(json, views, image.uri, mime_type.c_str(), img_data, output_path, info.kind, settings.texture_embed); + writeImageData(json, views, index, image.uri, mime_type.c_str(), img_data, output_path, info.kind, settings.texture_embed); } -void writeEncodedImage(std::string& json, std::vector& views, const cgltf_image& image, const std::string& encoded, const ImageInfo& info, const char* output_path, const Settings& settings) +void writeImageError(std::string& json, const char* action, size_t index, const char* uri, const char* reason) { - writeImageData(json, views, image.uri, "image/ktx2", encoded, output_path, info.kind, settings.texture_embed); + (void)json; + + fprintf(stderr, "Warning: unable to %s image %d (%s), skipping%s%s%s\n", action, int(index), uri ? uri : "embedded", reason ? " (" : "", reason ? reason : "", reason ? ")" : ""); +} + +void writeEncodedImage(std::string& json, std::vector& views, const cgltf_image& image, const std::string& encoded, const ImageInfo& info, size_t index, const char* output_path, const Settings& settings) +{ + writeImageData(json, views, index, image.uri, "image/ktx2", encoded, output_path, info.kind, settings.texture_embed); } void writeTexture(std::string& json, const cgltf_texture& texture, const ImageInfo* info, cgltf_data* data, const Settings& settings) From e20baef154adb3c1d3d6a560440120dffab6533b Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Mon, 8 Apr 2024 17:19:34 -0400 Subject: [PATCH 2/2] gltfpack: Use ERR Base64 embedded data for invalid images This prevents errors around missing images in case we can't find the source image or can't encode it. Loading the resulting glTF file will result in a PNG decode error. Unfortunately, files like this are still treated as invalid by glTF spec/validator. --- gltf/write.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gltf/write.cpp b/gltf/write.cpp index 7eae0d6c8..96794bb80 100644 --- a/gltf/write.cpp +++ b/gltf/write.cpp @@ -948,7 +948,9 @@ void writeImage(std::string& json, std::vector& views, const cgltf_i void writeImageError(std::string& json, const char* action, size_t index, const char* uri, const char* reason) { - (void)json; + append(json, "\"uri\":\""); + append(json, "data:image/png;base64,ERR/"); + append(json, "\""); fprintf(stderr, "Warning: unable to %s image %d (%s), skipping%s%s%s\n", action, int(index), uri ? uri : "embedded", reason ? " (" : "", reason ? reason : "", reason ? ")" : ""); }