diff --git a/tests/tester.cc b/tests/tester.cc index c047e4e..95cc93d 100644 --- a/tests/tester.cc +++ b/tests/tester.cc @@ -474,7 +474,7 @@ TEST_CASE("image-uri-spaces", "[issue-236]") { } REQUIRE(true == ret); REQUIRE(err.empty()); - REQUIRE(!warn.empty()); // relative image path won't exist in tests/ + REQUIRE(warn.empty()); REQUIRE(saved.images.size() == model.images.size()); // The image uri in CubeImageUriMultipleSpaces.gltf is not encoded and @@ -662,10 +662,11 @@ TEST_CASE("serialize-image-callback", "[issue-394]") { auto writer = [](const std::string *basepath, const std::string *filename, const tinygltf::Image *image, bool embedImages, - const tinygltf::URICallbacks *uri_cb, std::string *out_uri, - void *user_pointer) -> bool { + const tinygltf::FsCallbacks* fs, const tinygltf::URICallbacks *uri_cb, + std::string *out_uri, void *user_pointer) -> bool { (void)basepath; (void)image; + (void)fs; (void)uri_cb; REQUIRE(*filename == "foo"); REQUIRE(embedImages == true); @@ -699,12 +700,13 @@ TEST_CASE("serialize-image-failure", "[issue-394]") { auto writer = [](const std::string *basepath, const std::string *filename, const tinygltf::Image *image, bool embedImages, - const tinygltf::URICallbacks *uri_cb, std::string *out_uri, - void *user_pointer) -> bool { + const tinygltf::FsCallbacks* fs, const tinygltf::URICallbacks *uri_cb, + std::string *out_uri, void *user_pointer) -> bool { (void)basepath; (void)filename; (void)image; (void)embedImages; + (void)fs; (void)uri_cb; (void)out_uri; (void)user_pointer; @@ -1056,3 +1058,31 @@ TEST_CASE("serialize-lods", "[lods]") { CHECK(nodeWithoutLods.extensions.count("MSFT_lod") == 0); } } + +TEST_CASE("write-image-issue", "[issue-473]") { + + tinygltf::Model model; + tinygltf::TinyGLTF ctx; + std::string err; + std::string warn; + bool ok = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/Cube/Cube.gltf"); + REQUIRE(ok); + REQUIRE(err.empty()); + REQUIRE(warn.empty()); + + REQUIRE(model.images.size() == 2); + REQUIRE(model.images[0].uri == "Cube_BaseColor.png"); + REQUIRE(model.images[1].uri == "Cube_MetallicRoughness.png"); + + REQUIRE_FALSE(model.images[0].image.empty()); + REQUIRE_FALSE(model.images[1].image.empty()); + + ok = ctx.WriteGltfSceneToFile(&model, "Cube.gltf", false, true); + REQUIRE(ok); + + for (const auto& image : model.images) + { + std::fstream file(image.uri); + CHECK(file.good()); + } +} diff --git a/tiny_gltf.h b/tiny_gltf.h index 9c3d075..44a291f 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -1292,39 +1292,6 @@ struct URICallbacks { void *user_data; // An argument that is passed to all uri callbacks }; -/// -/// LoadImageDataFunction type. Signature for custom image loading callbacks. -/// -using LoadImageDataFunction = std::function; - -/// -/// WriteImageDataFunction type. Signature for custom image writing callbacks. -/// The out_uri parameter becomes the URI written to the gltf and may reference -/// a file or contain a data URI. -/// -using WriteImageDataFunction = std::function; - -#ifndef TINYGLTF_NO_STB_IMAGE -// Declaration of default image loader callback -bool LoadImageData(Image *image, const int image_idx, std::string *err, - std::string *warn, int req_width, int req_height, - const unsigned char *bytes, int size, void *); -#endif - -#ifndef TINYGLTF_NO_STB_IMAGE_WRITE -// Declaration of default image writer callback -bool WriteImageData(const std::string *basepath, const std::string *filename, - const Image *image, bool embedImages, - const URICallbacks *uri_cb, std::string *out_uri, void *); -#endif - /// /// FileExistsFunction type. Signature for custom filesystem callbacks. /// @@ -1396,6 +1363,40 @@ bool GetFileSizeInBytes(size_t *filesize_out, std::string *err, const std::string &filepath, void *); #endif +/// +/// LoadImageDataFunction type. Signature for custom image loading callbacks. +/// +using LoadImageDataFunction = std::function; + +/// +/// WriteImageDataFunction type. Signature for custom image writing callbacks. +/// The out_uri parameter becomes the URI written to the gltf and may reference +/// a file or contain a data URI. +/// +using WriteImageDataFunction = std::function; + +#ifndef TINYGLTF_NO_STB_IMAGE +// Declaration of default image loader callback +bool LoadImageData(Image *image, const int image_idx, std::string *err, + std::string *warn, int req_width, int req_height, + const unsigned char *bytes, int size, void *); +#endif + +#ifndef TINYGLTF_NO_STB_IMAGE_WRITE +// Declaration of default image writer callback +bool WriteImageData(const std::string *basepath, const std::string *filename, + const Image *image, bool embedImages, + const FsCallbacks* fs_cb, const URICallbacks *uri_cb, + std::string *out_uri, void *); +#endif + /// /// glTF Parser/Serializer context. /// @@ -2725,8 +2726,8 @@ static void WriteToMemory_stbi(void *context, void *data, int size) { bool WriteImageData(const std::string *basepath, const std::string *filename, const Image *image, bool embedImages, - const URICallbacks *uri_cb, std::string *out_uri, - void *fsPtr) { + const FsCallbacks* fs_cb, const URICallbacks *uri_cb, + std::string *out_uri, void *) { const std::string ext = GetFilePathExtension(*filename); // Write image to temporary buffer @@ -2775,12 +2776,11 @@ bool WriteImageData(const std::string *basepath, const std::string *filename, } } else { // Write image to disc - FsCallbacks *fs = reinterpret_cast(fsPtr); - if ((fs != nullptr) && (fs->WriteWholeFile != nullptr)) { + if ((fs_cb != nullptr) && (fs_cb->WriteWholeFile != nullptr)) { const std::string imagefilepath = JoinPath(*basepath, *filename); std::string writeError; - if (!fs->WriteWholeFile(&writeError, imagefilepath, data, - fs->user_data)) { + if (!fs_cb->WriteWholeFile(&writeError, imagefilepath, data, + fs_cb->user_data)) { // Could not write image file to disc; Throw error ? return false; } @@ -3233,6 +3233,7 @@ static std::string MimeToExt(const std::string &mimeType) { static bool UpdateImageObject(const Image &image, std::string &baseDir, int index, bool embedImages, + const FsCallbacks *fs_cb, const URICallbacks *uri_cb, const WriteImageDataFunction& WriteImageData, void *user_data, std::string *out_uri) { @@ -3266,7 +3267,7 @@ static bool UpdateImageObject(const Image &image, std::string &baseDir, bool imageWritten = false; if (WriteImageData != nullptr && !filename.empty() && !image.image.empty()) { imageWritten = WriteImageData(&baseDir, &filename, &image, embedImages, - uri_cb, out_uri, user_data); + fs_cb, uri_cb, out_uri, user_data); if (!imageWritten) { return false; } @@ -8547,7 +8548,7 @@ bool TinyGLTF::WriteGltfSceneToStream(const Model *model, std::ostream &stream, // we std::string uri; if (!UpdateImageObject(model->images[i], dummystring, int(i), true, - &uri_cb, this->WriteImageData, + &fs, &uri_cb, this->WriteImageData, this->write_image_user_data_, &uri)) { return false; } @@ -8655,7 +8656,7 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model, std::string uri; if (!UpdateImageObject(model->images[i], baseDir, int(i), embedImages, - &uri_cb, this->WriteImageData, + &fs, &uri_cb, this->WriteImageData, this->write_image_user_data_, &uri)) { return false; }