Compare commits

..

12 Commits

Author SHA1 Message Date
Syoyo Fujita
c2ca97b38b v2.8.1 2023-01-13 18:15:21 +09:00
Syoyo Fujita
f051892c55 Merge pull request #399 from e2e4e6/texture_sampler_name_fix
Missed serialization texture sampler name fixed.
2023-01-13 18:13:12 +09:00
s00665032
137a7ca999 Missed serialization texture sampler name fixed.
According to the glTF 2.0 specification it exists, the internal tinygltf structure contains 'name' field as well.
2023-01-13 12:52:08 +07:00
Syoyo Fujita
477d977fea Merge pull request #398 from nicolas-raoul/patch-1
Fixed typo
2023-01-12 16:21:35 +09:00
Nicolas Raoul
8cd5e759d0 Fixed typo 2023-01-12 15:29:32 +09:00
Syoyo Fujita
a6c3945ed3 Bump version 2.8.0. 2023-01-10 20:42:24 +09:00
Syoyo Fujita
6614bddef3 Merge pull request #397 from pknowlesnv/encode_image_uri
urlencode image urls
2023-01-10 20:31:39 +09:00
Pyarelal Knowles
385946dfd8 add URI encode/decode API
Tinygltf is able to write files defined by a URI, so it needs to be able
to decode it. Since it may also modify the path where the image is saved
it may need to re-encode the URI too. This patch provides an API to set
URI encoding and decoding callbacks and exposes the default decode
method.

Uses the existing dlib::urldecode as a decode default. The encode
callback is left null, matching existing behaviour.

Updates the WriteImageDataFunction signature to include
tinygltf::URICallbacks.

Decodes the image and buffer uris before using them as a filename.

If the encode callback is set, encodes the written image location in the
default WriteImageDataFunction and encodes generated buffer locations
when writing .bin files.

Adds a save+load step to the test image-uri-spaces to verify uri
encoding.
2023-01-09 20:54:29 -08:00
Syoyo Fujita
03bbe0921c Merge pull request #396 from pknowlesnv/image_write_failure
propagate image writing failures
2022-12-30 17:59:41 +09:00
Pyarelal Knowles
a9121550b9 SerializeGltfImage: add missing & std::string ref
Hopefully the compiler would optimize this away but better to avoid the
copy in the first place.
2022-12-29 14:12:29 -08:00
Pyarelal Knowles
d2b0af6915 propagate image writing failures
Modifies UpdateImageObject() so that Returning false from the
WriteImageDataFunction callback results in the WriteGltfScene*() call
returning false.

Does not call WriteImageDataFunction if there is no image data.

Adds test case serialize-image-failure to verify the callback return
code is able to cause an overall failure to save the gltf.
2022-12-29 13:50:17 -08:00
Syoyo Fujita
695608dd11 Update readme. 2022-12-29 21:50:47 +09:00
3 changed files with 289 additions and 49 deletions

View File

@@ -2,20 +2,22 @@
`TinyGLTF` is a header only C++11 glTF 2.0 https://github.com/KhronosGroup/glTF library.
`TinyGLTF` uses Niels Lohmann's json library(https://github.com/nlohmann/json), so now it requires C++11 compiler.
`TinyGLTF` uses Niels Lohmann's json library (https://github.com/nlohmann/json), so now it requires C++11 compiler.
(Also, you can use RadpidJSON as an JSON backend)
If you are looking for old, C++03 version, please use `devel-picojson` branch(but not maintained anymore).
If you are looking for old, C++03 version, please use `devel-picojson` branch (but not maintained anymore).
## Status
Currently TinyGLTF is stable and maintainance mode. No drastic changes and feature additions planned.
Currently TinyGLTF is stable and maintenance mode. No drastic changes and feature additions planned.
- v2.8.0 Add URICallbacks for custom URI handling in Buffer and Image. PR#397
- v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393
- v2.6.0 Support serializing sparse accessor(Thanks to @fynv).
- v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
- v2.4.0 Experimental RapidJSON support. Experimental C++14 support(C++14 may give better performance)
- v2.3.0 Modified Material representation according to glTF 2.0 schema(and introduced TextureInfo class)
- v2.2.0 release(Support loading 16bit PNG. Sparse accessor support)
- v2.1.0 release(Draco support)
- v2.1.0 release(Draco decoding support)
- v2.0.0 release(22 Aug, 2018)!
### Branches

View File

@@ -392,27 +392,105 @@ TEST_CASE("pbr-khr-texture-transform", "[material]") {
TEST_CASE("image-uri-spaces", "[issue-236]") {
tinygltf::Model model;
tinygltf::TinyGLTF ctx;
std::string err;
std::string warn;
// Test image file with single spaces.
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriSpaces.gltf");
if (!err.empty()) {
std::cerr << err << std::endl;
}
{
tinygltf::Model model;
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/CubeImageUriSpaces/CubeImageUriSpaces.gltf");
if (!warn.empty()) {
std::cerr << warn << std::endl;
}
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(true == ret);
REQUIRE(warn.empty());
REQUIRE(err.empty());
REQUIRE(model.images.size() == 1);
REQUIRE(model.images[0].uri.find(' ') != std::string::npos);
}
// Test image file with a beginning space, trailing space, and greater than
// one consecutive spaces.
ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf");
tinygltf::Model model;
bool ret = ctx.LoadASCIIFromFile(
&model, &err, &warn,
"../models/CubeImageUriSpaces/CubeImageUriMultipleSpaces.gltf");
if (!warn.empty()) {
std::cerr << warn << std::endl;
}
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(warn.empty());
REQUIRE(err.empty());
REQUIRE(model.images.size() == 1);
REQUIRE(model.images[0].uri.size() > 1);
REQUIRE(model.images[0].uri[0] == ' ');
// Test the URI encoding API by saving and re-load the file, without embedding
// the image.
// TODO(syoyo): create temp directory.
{
// Encoder that only replaces spaces with "%20".
auto uriencode = [](const std::string &in_uri,
const std::string &object_type, std::string *out_uri,
void *user_data) -> bool {
(void)user_data;
bool imageOrBuffer = object_type == "image" || object_type == "buffer";
REQUIRE(true == imageOrBuffer);
*out_uri = {};
for (char c : in_uri) {
if (c == ' ')
*out_uri += "%20";
else
*out_uri += c;
}
return true;
};
// Remove the buffer URI, so a new one is generated based on the gltf
// filename and then encoded with the above callback.
model.buffers[0].uri.clear();
tinygltf::URICallbacks uri_cb{uriencode, tinygltf::URIDecode, nullptr};
ctx.SetURICallbacks(uri_cb);
ret = ctx.WriteGltfSceneToFile(&model, " issue-236.gltf", false, false);
REQUIRE(true == ret);
// read back serialized glTF
tinygltf::Model saved;
bool ret = ctx.LoadASCIIFromFile(&saved, &err, &warn, " issue-236.gltf");
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(err.empty());
REQUIRE(!warn.empty()); // relative image path won't exist in tests/
REQUIRE(saved.images.size() == model.images.size());
// The image uri in CubeImageUriMultipleSpaces.gltf is not encoded and
// should be different after encoding spaces with %20.
REQUIRE(model.images[0].uri != saved.images[0].uri);
// Verify the image path remains the same after uri decoding
std::string image_uri, image_uri_saved;
(void)tinygltf::URIDecode(model.images[0].uri, &image_uri, nullptr);
(void)tinygltf::URIDecode(saved.images[0].uri, &image_uri_saved, nullptr);
REQUIRE(image_uri == image_uri_saved);
// Verify the buffer's generated and encoded URI
REQUIRE(saved.buffers.size() == model.buffers.size());
REQUIRE(saved.buffers[0].uri == "%20issue-236.bin");
}
}
TEST_CASE("serialize-empty-material", "[issue-294]") {
@@ -583,7 +661,11 @@ TEST_CASE("serialize-image-callback", "[issue-394]") {
auto writer = [](const std::string *basepath, const std::string *filename,
const tinygltf::Image *image, bool embedImages,
std::string *out_uri, void *user_pointer) -> bool {
const tinygltf::URICallbacks *uri_cb, std::string *out_uri,
void *user_pointer) -> bool {
(void)basepath;
(void)image;
(void)uri_cb;
REQUIRE(*filename == "foo");
REQUIRE(embedImages == true);
REQUIRE(user_pointer == (void *)0xba5e1e55);
@@ -593,13 +675,46 @@ TEST_CASE("serialize-image-callback", "[issue-394]") {
tinygltf::TinyGLTF ctx;
ctx.SetImageWriter(writer, (void *)0xba5e1e55);
ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
bool result = ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
// use nlohmann json
nlohmann::json j = nlohmann::json::parse(os.str());
REQUIRE(true == result);
REQUIRE(1 == j["images"].size());
REQUIRE(j["images"][0].is_object());
REQUIRE(j["images"][0]["uri"].get<std::string>() == "bar");
}
TEST_CASE("serialize-image-failure", "[issue-394]") {
tinygltf::Model m;
tinygltf::Image i;
// Set some data so the ImageWriter callback will be called
i.image = {255, 255, 255, 255};
m.images.push_back(i);
std::stringstream os;
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 {
(void)basepath;
(void)filename;
(void)image;
(void)embedImages;
(void)uri_cb;
(void)out_uri;
(void)user_pointer;
return false;
};
tinygltf::TinyGLTF ctx;
ctx.SetImageWriter(writer, (void *)0xba5e1e55);
bool result = ctx.WriteGltfSceneToStream(const_cast<const tinygltf::Model *>(&m), os, false,
false);
REQUIRE(false == result);
REQUIRE(os.str().size() == 0);
}

View File

@@ -26,6 +26,8 @@
// THE SOFTWARE.
// Version:
// - v2.8.1 Missed serialization texture sampler name fixed. PR#399.
// - v2.8.0 Add URICallbacks for custom URI handling in Buffer and Image. PR#397.
// - v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393.
// - v2.6.3 Fix GLB file with empty BIN chunk was not handled. PR#382 and PR#383.
// - v2.6.2 Fix out-of-bounds access of accessors. PR#379.
@@ -1207,6 +1209,39 @@ enum SectionCheck {
REQUIRE_ALL = 0x7f
};
///
/// URIEncodeFunction type. Signature for custom URI encoding of external
/// resources such as .bin and image files. Used by tinygltf to re-encode the
/// final location of saved files. object_type may be used to encode buffer and
/// image URIs differently, for example. See
/// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#uris
///
typedef bool (*URIEncodeFunction)(const std::string &in_uri,
const std::string &object_type,
std::string *out_uri, void *user_data);
///
/// URIDecodeFunction type. Signature for custom URI decoding of external
/// resources such as .bin and image files. Used by tinygltf when computing
/// filenames to write resources.
///
typedef bool (*URIDecodeFunction)(const std::string &in_uri,
std::string *out_uri, void *user_data);
// Declaration of default uri decode function
bool URIDecode(const std::string &in_uri, std::string *out_uri,
void *user_data);
///
/// A structure containing URI callbacks and a pointer to their user data.
///
struct URICallbacks {
URIEncodeFunction encode; // Optional encode method
URIDecodeFunction decode; // Required decode method
void *user_data; // An argument that is passed to all uri callbacks
};
///
/// LoadImageDataFunction type. Signature for custom image loading callbacks.
///
@@ -1223,7 +1258,9 @@ typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
typedef bool (*WriteImageDataFunction)(const std::string *basepath,
const std::string *filename,
const Image *image, bool embedImages,
std::string *out_uri, void *user_pointer);
const URICallbacks *uri_cb,
std::string *out_uri,
void *user_pointer);
#ifndef TINYGLTF_NO_STB_IMAGE
// Declaration of default image loader callback
@@ -1235,8 +1272,8 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
#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, std::string *out_uri,
void *);
const Image *image, bool embedImages,
const URICallbacks *uri_cb, std::string *out_uri, void *);
#endif
///
@@ -1388,6 +1425,11 @@ class TinyGLTF {
///
void SetImageWriter(WriteImageDataFunction WriteImageData, void *user_data);
///
/// Set callbacks to use for URI encoding and decoding and their user data
///
void SetURICallbacks(URICallbacks callbacks);
///
/// Set callbacks to use for filesystem (fs) access and their user data
///
@@ -1470,6 +1512,15 @@ class TinyGLTF {
#endif
};
URICallbacks uri_cb = {
// Use paths as-is by default. This will use JSON string escaping.
nullptr,
// Decode all URIs before using them as paths as the application may have
// percent encoded them.
&tinygltf::URIDecode,
// URI callback user data
nullptr};
LoadImageDataFunction LoadImageData =
#ifndef TINYGLTF_NO_STB_IMAGE
&tinygltf::LoadImageData;
@@ -2291,6 +2342,13 @@ static const std::string urldecode(const std::string &str) {
} // namespace dlib
// --- dlib end --------------------------------------------------------------
bool URIDecode(const std::string &in_uri, std::string *out_uri,
void *user_data) {
(void)user_data;
*out_uri = dlib::urldecode(in_uri);
return true;
}
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
std::string *warn, const std::string &filename,
const std::string &basedir, bool required,
@@ -2501,7 +2559,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, std::string *out_uri,
const Image *image, bool embedImages,
const URICallbacks *uri_cb, std::string *out_uri,
void *fsPtr) {
const std::string ext = GetFilePathExtension(*filename);
@@ -2563,13 +2622,26 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
} else {
// Throw error?
}
*out_uri = *filename;
if (uri_cb->encode) {
if (!uri_cb->encode(*filename, "image", out_uri, uri_cb->user_data)) {
return false;
}
} else {
*out_uri = *filename;
}
}
return true;
}
#endif
void TinyGLTF::SetURICallbacks(URICallbacks callbacks) {
assert(callbacks.decode);
if (callbacks.decode) {
uri_cb = callbacks;
}
}
void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) { fs = callbacks; }
#ifdef _WIN32
@@ -2834,15 +2906,21 @@ static std::string MimeToExt(const std::string &mimeType) {
return "";
}
static void UpdateImageObject(const Image &image, std::string &baseDir,
static bool UpdateImageObject(const Image &image, std::string &baseDir,
int index, bool embedImages,
const URICallbacks *uri_cb,
WriteImageDataFunction *WriteImageData,
std::string *out_uri, void *user_data) {
void *user_data, std::string *out_uri) {
std::string filename;
std::string ext;
// If image has uri, use it as a filename
if (image.uri.size()) {
filename = GetBaseFilename(image.uri);
std::string decoded_uri;
if (!uri_cb->decode(image.uri, &decoded_uri, uri_cb->user_data)) {
// A decode failure results in a failure to write the gltf.
return false;
}
filename = GetBaseFilename(decoded_uri);
ext = GetFilePathExtension(filename);
} else if (image.bufferView != -1) {
// If there's no URI and the data exists in a buffer,
@@ -2857,17 +2935,24 @@ static void UpdateImageObject(const Image &image, std::string &baseDir,
filename = std::to_string(index) + "." + ext;
}
// If callback is set, modify image data object
// If callback is set and image data exists, modify image data object. If
// image data does not exist, this is not considered a failure and the
// original uri should be maintained.
bool imageWritten = false;
if (*WriteImageData != nullptr && !filename.empty()) {
if (*WriteImageData != nullptr && !filename.empty() && !image.image.empty()) {
imageWritten = (*WriteImageData)(&baseDir, &filename, &image, embedImages,
out_uri, user_data);
uri_cb, out_uri, user_data);
if (!imageWritten) {
return false;
}
}
// Use the original uri if the image was not written.
if (!imageWritten) {
*out_uri = image.uri;
}
return true;
}
bool IsDataURI(const std::string &in) {
@@ -3786,6 +3871,7 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
std::string *warn, const json &o,
bool store_original_json_for_extras_and_extensions,
const std::string &basedir, FsCallbacks *fs,
const URICallbacks *uri_cb,
LoadImageDataFunction *LoadImageData = nullptr,
void *load_image_user_data = nullptr) {
// A glTF image must either reference a bufferView or an image uri
@@ -3896,7 +3982,18 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
#ifdef TINYGLTF_NO_EXTERNAL_IMAGE
return true;
#else
std::string decoded_uri = dlib::urldecode(uri);
std::string decoded_uri;
if (!uri_cb->decode(uri, &decoded_uri, uri_cb->user_data)) {
if (warn) {
(*warn) += "Failed to decode 'uri' for image[" +
std::to_string(image_idx) + "] name = [" + image->name +
"]\n";
}
// Image loading failure is not critical to overall gltf loading.
return true;
}
if (!LoadExternalFile(&img, err, warn, decoded_uri, basedir,
/* required */ false, /* required bytes */ 0,
/* checksize */ false, fs)) {
@@ -4075,8 +4172,8 @@ static bool ParseOcclusionTextureInfo(
static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
bool store_original_json_for_extras_and_extensions,
FsCallbacks *fs, const std::string &basedir,
bool is_binary = false,
FsCallbacks *fs, const URICallbacks *uri_cb,
const std::string &basedir, bool is_binary = false,
const unsigned char *bin_data = nullptr,
size_t bin_size = 0) {
size_t byteLength;
@@ -4122,7 +4219,10 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
}
} else {
// External .bin file.
std::string decoded_uri = dlib::urldecode(buffer->uri);
std::string decoded_uri;
if (!uri_cb->decode(buffer->uri, &decoded_uri, uri_cb->user_data)) {
return false;
}
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr,
decoded_uri, basedir, /* required */ true,
byteLength, /* checkSize */ true, fs)) {
@@ -4167,7 +4267,10 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
}
} else {
// Assume external .bin file.
std::string decoded_uri = dlib::urldecode(buffer->uri);
std::string decoded_uri;
if (!uri_cb->decode(buffer->uri, &decoded_uri, uri_cb->user_data)) {
return false;
}
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, decoded_uri,
basedir, /* required */ true, byteLength,
/* checkSize */ true, fs)) {
@@ -5710,7 +5813,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
Buffer buffer;
if (!ParseBuffer(&buffer, err, o,
store_original_json_for_extras_and_extensions_, &fs,
base_dir, is_binary_, bin_data_, bin_size_)) {
&uri_cb, base_dir, is_binary_, bin_data_, bin_size_)) {
return false;
}
@@ -5981,7 +6084,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
Image image;
if (!ParseImage(&image, idx, err, warn, o,
store_original_json_for_extras_and_extensions_, base_dir,
&fs, &this->LoadImageData, load_image_user_data)) {
&fs, &uri_cb, &this->LoadImageData,
load_image_user_data)) {
return false;
}
@@ -6977,10 +7081,10 @@ static void SerializeGltfBuffer(const Buffer &buffer, json &o) {
static bool SerializeGltfBuffer(const Buffer &buffer, json &o,
const std::string &binFilename,
const std::string &binBaseFilename) {
const std::string &binUri) {
if (!SerializeGltfBufferData(buffer.data, binFilename)) return false;
SerializeNumberProperty("byteLength", buffer.data.size(), o);
SerializeStringProperty("uri", binBaseFilename, o);
SerializeStringProperty("uri", binUri, o);
if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
@@ -7016,7 +7120,7 @@ static void SerializeGltfBufferView(const BufferView &bufferView, json &o) {
}
}
static void SerializeGltfImage(const Image &image, const std::string uri,
static void SerializeGltfImage(const Image &image, const std::string &uri,
json &o) {
// From 2.7.0, we look for `uri` parameter, not `Image.uri`
// if uri is empty, the mimeType and bufferview should be set
@@ -7024,7 +7128,6 @@ static void SerializeGltfImage(const Image &image, const std::string uri,
SerializeStringProperty("mimeType", image.mimeType, o);
SerializeNumberProperty<int>("bufferView", image.bufferView, o);
} else {
// TODO(syoyo): dlib::urilencode?
SerializeStringProperty("uri", uri, o);
}
@@ -7338,6 +7441,9 @@ static void SerializeGltfNode(const Node &node, json &o) {
}
static void SerializeGltfSampler(const Sampler &sampler, json &o) {
if (!sampler.name.empty()) {
SerializeStringProperty("name", sampler.name, o);
}
if (sampler.magFilter != -1) {
SerializeNumberProperty("magFilter", sampler.magFilter, o);
}
@@ -7817,9 +7923,11 @@ bool TinyGLTF::WriteGltfSceneToStream(const Model *model, std::ostream &stream,
// enabled, since we won't write separate images when writing to a stream
// we
std::string uri;
UpdateImageObject(model->images[i], dummystring, int(i), true,
&this->WriteImageData, &uri,
this->write_image_user_data_);
if (!UpdateImageObject(model->images[i], dummystring, int(i), true,
&uri_cb, &this->WriteImageData,
this->write_image_user_data_, &uri)) {
return false;
}
SerializeGltfImage(model->images[i], uri, image);
JsonPushBack(images, std::move(image));
}
@@ -7856,7 +7964,7 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
SerializeGltfModel(model, output);
// BUFFERS
std::vector<std::string> usedUris;
std::vector<std::string> usedFilenames;
std::vector<unsigned char> binBuffer;
if (model->buffers.size()) {
json buffers;
@@ -7869,27 +7977,40 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
SerializeGltfBuffer(model->buffers[i], buffer);
} else {
std::string binSavePath;
std::string binFilename;
std::string binUri;
if (!model->buffers[i].uri.empty() &&
!IsDataURI(model->buffers[i].uri)) {
binUri = model->buffers[i].uri;
if (!uri_cb.decode(binUri, &binFilename, uri_cb.user_data)) {
return false;
}
} else {
binUri = defaultBinFilename + defaultBinFileExt;
binFilename = defaultBinFilename + defaultBinFileExt;
bool inUse = true;
int numUsed = 0;
while (inUse) {
inUse = false;
for (const std::string &usedName : usedUris) {
if (binUri.compare(usedName) != 0) continue;
for (const std::string &usedName : usedFilenames) {
if (binFilename.compare(usedName) != 0) continue;
inUse = true;
binUri = defaultBinFilename + std::to_string(numUsed++) +
defaultBinFileExt;
binFilename = defaultBinFilename + std::to_string(numUsed++) +
defaultBinFileExt;
break;
}
}
if (uri_cb.encode) {
if (!uri_cb.encode(binFilename, "buffer", &binUri,
uri_cb.user_data)) {
return false;
}
} else {
binUri = binFilename;
}
}
usedUris.push_back(binUri);
binSavePath = JoinPath(baseDir, binUri);
usedFilenames.push_back(binFilename);
binSavePath = JoinPath(baseDir, binFilename);
if (!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
binUri)) {
return false;
@@ -7908,9 +8029,11 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
json image;
std::string uri;
UpdateImageObject(model->images[i], baseDir, int(i), embedImages,
&this->WriteImageData, &uri,
this->write_image_user_data_);
if (!UpdateImageObject(model->images[i], baseDir, int(i), embedImages,
&uri_cb, &this->WriteImageData,
this->write_image_user_data_, &uri)) {
return false;
}
SerializeGltfImage(model->images[i], uri, image);
JsonPushBack(images, std::move(image));
}