mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-07-04 04:45:12 +08:00
Merge pull request #397 from pknowlesnv/encode_image_uri
urlencode image urls
This commit is contained in:
commit
6614bddef3
108
tests/tester.cc
108
tests/tester.cc
@ -392,27 +392,105 @@ TEST_CASE("pbr-khr-texture-transform", "[material]") {
|
|||||||
|
|
||||||
TEST_CASE("image-uri-spaces", "[issue-236]") {
|
TEST_CASE("image-uri-spaces", "[issue-236]") {
|
||||||
|
|
||||||
tinygltf::Model model;
|
|
||||||
tinygltf::TinyGLTF ctx;
|
tinygltf::TinyGLTF ctx;
|
||||||
std::string err;
|
std::string err;
|
||||||
std::string warn;
|
std::string warn;
|
||||||
|
|
||||||
// Test image file with single spaces.
|
// Test image file with single spaces.
|
||||||
bool ret = ctx.LoadASCIIFromFile(&model, &err, &warn, "../models/CubeImageUriSpaces/CubeImageUriSpaces.gltf");
|
{
|
||||||
if (!err.empty()) {
|
tinygltf::Model model;
|
||||||
std::cerr << err << std::endl;
|
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
|
// Test image file with a beginning space, trailing space, and greater than
|
||||||
// one consecutive spaces.
|
// 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()) {
|
if (!err.empty()) {
|
||||||
std::cerr << err << std::endl;
|
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.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]") {
|
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,
|
auto writer = [](const std::string *basepath, const std::string *filename,
|
||||||
const tinygltf::Image *image, bool embedImages,
|
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(*filename == "foo");
|
||||||
REQUIRE(embedImages == true);
|
REQUIRE(embedImages == true);
|
||||||
REQUIRE(user_pointer == (void *)0xba5e1e55);
|
REQUIRE(user_pointer == (void *)0xba5e1e55);
|
||||||
@ -616,7 +698,15 @@ TEST_CASE("serialize-image-failure", "[issue-394]") {
|
|||||||
|
|
||||||
auto writer = [](const std::string *basepath, const std::string *filename,
|
auto writer = [](const std::string *basepath, const std::string *filename,
|
||||||
const tinygltf::Image *image, bool embedImages,
|
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)filename;
|
||||||
|
(void)image;
|
||||||
|
(void)embedImages;
|
||||||
|
(void)uri_cb;
|
||||||
|
(void)out_uri;
|
||||||
|
(void)user_pointer;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
167
tiny_gltf.h
167
tiny_gltf.h
@ -1207,6 +1207,39 @@ enum SectionCheck {
|
|||||||
REQUIRE_ALL = 0x7f
|
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.
|
/// LoadImageDataFunction type. Signature for custom image loading callbacks.
|
||||||
///
|
///
|
||||||
@ -1223,7 +1256,9 @@ typedef bool (*LoadImageDataFunction)(Image *, const int, std::string *,
|
|||||||
typedef bool (*WriteImageDataFunction)(const std::string *basepath,
|
typedef bool (*WriteImageDataFunction)(const std::string *basepath,
|
||||||
const std::string *filename,
|
const std::string *filename,
|
||||||
const Image *image, bool embedImages,
|
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
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||||
// Declaration of default image loader callback
|
// Declaration of default image loader callback
|
||||||
@ -1235,8 +1270,8 @@ bool LoadImageData(Image *image, const int image_idx, std::string *err,
|
|||||||
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
#ifndef TINYGLTF_NO_STB_IMAGE_WRITE
|
||||||
// Declaration of default image writer callback
|
// Declaration of default image writer callback
|
||||||
bool WriteImageData(const std::string *basepath, const std::string *filename,
|
bool WriteImageData(const std::string *basepath, const std::string *filename,
|
||||||
const Image *image, bool embedImages, std::string *out_uri,
|
const Image *image, bool embedImages,
|
||||||
void *);
|
const URICallbacks *uri_cb, std::string *out_uri, void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -1388,6 +1423,11 @@ class TinyGLTF {
|
|||||||
///
|
///
|
||||||
void SetImageWriter(WriteImageDataFunction WriteImageData, void *user_data);
|
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
|
/// Set callbacks to use for filesystem (fs) access and their user data
|
||||||
///
|
///
|
||||||
@ -1470,6 +1510,15 @@ class TinyGLTF {
|
|||||||
#endif
|
#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 =
|
LoadImageDataFunction LoadImageData =
|
||||||
#ifndef TINYGLTF_NO_STB_IMAGE
|
#ifndef TINYGLTF_NO_STB_IMAGE
|
||||||
&tinygltf::LoadImageData;
|
&tinygltf::LoadImageData;
|
||||||
@ -2291,6 +2340,13 @@ static const std::string urldecode(const std::string &str) {
|
|||||||
} // namespace dlib
|
} // namespace dlib
|
||||||
// --- dlib end --------------------------------------------------------------
|
// --- 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,
|
static bool LoadExternalFile(std::vector<unsigned char> *out, std::string *err,
|
||||||
std::string *warn, const std::string &filename,
|
std::string *warn, const std::string &filename,
|
||||||
const std::string &basedir, bool required,
|
const std::string &basedir, bool required,
|
||||||
@ -2501,7 +2557,8 @@ static void WriteToMemory_stbi(void *context, void *data, int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WriteImageData(const std::string *basepath, const std::string *filename,
|
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) {
|
void *fsPtr) {
|
||||||
const std::string ext = GetFilePathExtension(*filename);
|
const std::string ext = GetFilePathExtension(*filename);
|
||||||
|
|
||||||
@ -2563,13 +2620,26 @@ bool WriteImageData(const std::string *basepath, const std::string *filename,
|
|||||||
} else {
|
} else {
|
||||||
// Throw error?
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void TinyGLTF::SetURICallbacks(URICallbacks callbacks) {
|
||||||
|
assert(callbacks.decode);
|
||||||
|
if (callbacks.decode) {
|
||||||
|
uri_cb = callbacks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) { fs = callbacks; }
|
void TinyGLTF::SetFsCallbacks(FsCallbacks callbacks) { fs = callbacks; }
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -2836,13 +2906,19 @@ static std::string MimeToExt(const std::string &mimeType) {
|
|||||||
|
|
||||||
static bool UpdateImageObject(const Image &image, std::string &baseDir,
|
static bool UpdateImageObject(const Image &image, std::string &baseDir,
|
||||||
int index, bool embedImages,
|
int index, bool embedImages,
|
||||||
|
const URICallbacks *uri_cb,
|
||||||
WriteImageDataFunction *WriteImageData,
|
WriteImageDataFunction *WriteImageData,
|
||||||
std::string *out_uri, void *user_data) {
|
void *user_data, std::string *out_uri) {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
std::string ext;
|
std::string ext;
|
||||||
// If image has uri, use it as a filename
|
// If image has uri, use it as a filename
|
||||||
if (image.uri.size()) {
|
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);
|
ext = GetFilePathExtension(filename);
|
||||||
} else if (image.bufferView != -1) {
|
} else if (image.bufferView != -1) {
|
||||||
// If there's no URI and the data exists in a buffer,
|
// If there's no URI and the data exists in a buffer,
|
||||||
@ -2863,7 +2939,7 @@ static bool UpdateImageObject(const Image &image, std::string &baseDir,
|
|||||||
bool imageWritten = false;
|
bool imageWritten = false;
|
||||||
if (*WriteImageData != nullptr && !filename.empty() && !image.image.empty()) {
|
if (*WriteImageData != nullptr && !filename.empty() && !image.image.empty()) {
|
||||||
imageWritten = (*WriteImageData)(&baseDir, &filename, &image, embedImages,
|
imageWritten = (*WriteImageData)(&baseDir, &filename, &image, embedImages,
|
||||||
out_uri, user_data);
|
uri_cb, out_uri, user_data);
|
||||||
if (!imageWritten) {
|
if (!imageWritten) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3793,6 +3869,7 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
|||||||
std::string *warn, const json &o,
|
std::string *warn, const json &o,
|
||||||
bool store_original_json_for_extras_and_extensions,
|
bool store_original_json_for_extras_and_extensions,
|
||||||
const std::string &basedir, FsCallbacks *fs,
|
const std::string &basedir, FsCallbacks *fs,
|
||||||
|
const URICallbacks *uri_cb,
|
||||||
LoadImageDataFunction *LoadImageData = nullptr,
|
LoadImageDataFunction *LoadImageData = nullptr,
|
||||||
void *load_image_user_data = nullptr) {
|
void *load_image_user_data = nullptr) {
|
||||||
// A glTF image must either reference a bufferView or an image uri
|
// A glTF image must either reference a bufferView or an image uri
|
||||||
@ -3903,7 +3980,18 @@ static bool ParseImage(Image *image, const int image_idx, std::string *err,
|
|||||||
#ifdef TINYGLTF_NO_EXTERNAL_IMAGE
|
#ifdef TINYGLTF_NO_EXTERNAL_IMAGE
|
||||||
return true;
|
return true;
|
||||||
#else
|
#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,
|
if (!LoadExternalFile(&img, err, warn, decoded_uri, basedir,
|
||||||
/* required */ false, /* required bytes */ 0,
|
/* required */ false, /* required bytes */ 0,
|
||||||
/* checksize */ false, fs)) {
|
/* checksize */ false, fs)) {
|
||||||
@ -4082,8 +4170,8 @@ static bool ParseOcclusionTextureInfo(
|
|||||||
|
|
||||||
static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
|
static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
|
||||||
bool store_original_json_for_extras_and_extensions,
|
bool store_original_json_for_extras_and_extensions,
|
||||||
FsCallbacks *fs, const std::string &basedir,
|
FsCallbacks *fs, const URICallbacks *uri_cb,
|
||||||
bool is_binary = false,
|
const std::string &basedir, bool is_binary = false,
|
||||||
const unsigned char *bin_data = nullptr,
|
const unsigned char *bin_data = nullptr,
|
||||||
size_t bin_size = 0) {
|
size_t bin_size = 0) {
|
||||||
size_t byteLength;
|
size_t byteLength;
|
||||||
@ -4129,7 +4217,10 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// External .bin file.
|
// 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,
|
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr,
|
||||||
decoded_uri, basedir, /* required */ true,
|
decoded_uri, basedir, /* required */ true,
|
||||||
byteLength, /* checkSize */ true, fs)) {
|
byteLength, /* checkSize */ true, fs)) {
|
||||||
@ -4174,7 +4265,10 @@ static bool ParseBuffer(Buffer *buffer, std::string *err, const json &o,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Assume external .bin file.
|
// 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,
|
if (!LoadExternalFile(&buffer->data, err, /* warn */ nullptr, decoded_uri,
|
||||||
basedir, /* required */ true, byteLength,
|
basedir, /* required */ true, byteLength,
|
||||||
/* checkSize */ true, fs)) {
|
/* checkSize */ true, fs)) {
|
||||||
@ -5717,7 +5811,7 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
if (!ParseBuffer(&buffer, err, o,
|
if (!ParseBuffer(&buffer, err, o,
|
||||||
store_original_json_for_extras_and_extensions_, &fs,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5988,7 +6082,8 @@ bool TinyGLTF::LoadFromString(Model *model, std::string *err, std::string *warn,
|
|||||||
Image image;
|
Image image;
|
||||||
if (!ParseImage(&image, idx, err, warn, o,
|
if (!ParseImage(&image, idx, err, warn, o,
|
||||||
store_original_json_for_extras_and_extensions_, base_dir,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6984,10 +7079,10 @@ static void SerializeGltfBuffer(const Buffer &buffer, json &o) {
|
|||||||
|
|
||||||
static bool SerializeGltfBuffer(const Buffer &buffer, json &o,
|
static bool SerializeGltfBuffer(const Buffer &buffer, json &o,
|
||||||
const std::string &binFilename,
|
const std::string &binFilename,
|
||||||
const std::string &binBaseFilename) {
|
const std::string &binUri) {
|
||||||
if (!SerializeGltfBufferData(buffer.data, binFilename)) return false;
|
if (!SerializeGltfBufferData(buffer.data, binFilename)) return false;
|
||||||
SerializeNumberProperty("byteLength", buffer.data.size(), o);
|
SerializeNumberProperty("byteLength", buffer.data.size(), o);
|
||||||
SerializeStringProperty("uri", binBaseFilename, o);
|
SerializeStringProperty("uri", binUri, o);
|
||||||
|
|
||||||
if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
|
if (buffer.name.size()) SerializeStringProperty("name", buffer.name, o);
|
||||||
|
|
||||||
@ -7031,7 +7126,6 @@ static void SerializeGltfImage(const Image &image, const std::string &uri,
|
|||||||
SerializeStringProperty("mimeType", image.mimeType, o);
|
SerializeStringProperty("mimeType", image.mimeType, o);
|
||||||
SerializeNumberProperty<int>("bufferView", image.bufferView, o);
|
SerializeNumberProperty<int>("bufferView", image.bufferView, o);
|
||||||
} else {
|
} else {
|
||||||
// TODO(syoyo): dlib::urilencode?
|
|
||||||
SerializeStringProperty("uri", uri, o);
|
SerializeStringProperty("uri", uri, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7825,8 +7919,8 @@ bool TinyGLTF::WriteGltfSceneToStream(const Model *model, std::ostream &stream,
|
|||||||
// we
|
// we
|
||||||
std::string uri;
|
std::string uri;
|
||||||
if (!UpdateImageObject(model->images[i], dummystring, int(i), true,
|
if (!UpdateImageObject(model->images[i], dummystring, int(i), true,
|
||||||
&this->WriteImageData, &uri,
|
&uri_cb, &this->WriteImageData,
|
||||||
this->write_image_user_data_)) {
|
this->write_image_user_data_, &uri)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SerializeGltfImage(model->images[i], uri, image);
|
SerializeGltfImage(model->images[i], uri, image);
|
||||||
@ -7865,7 +7959,7 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
|
|||||||
SerializeGltfModel(model, output);
|
SerializeGltfModel(model, output);
|
||||||
|
|
||||||
// BUFFERS
|
// BUFFERS
|
||||||
std::vector<std::string> usedUris;
|
std::vector<std::string> usedFilenames;
|
||||||
std::vector<unsigned char> binBuffer;
|
std::vector<unsigned char> binBuffer;
|
||||||
if (model->buffers.size()) {
|
if (model->buffers.size()) {
|
||||||
json buffers;
|
json buffers;
|
||||||
@ -7878,27 +7972,40 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
|
|||||||
SerializeGltfBuffer(model->buffers[i], buffer);
|
SerializeGltfBuffer(model->buffers[i], buffer);
|
||||||
} else {
|
} else {
|
||||||
std::string binSavePath;
|
std::string binSavePath;
|
||||||
|
std::string binFilename;
|
||||||
std::string binUri;
|
std::string binUri;
|
||||||
if (!model->buffers[i].uri.empty() &&
|
if (!model->buffers[i].uri.empty() &&
|
||||||
!IsDataURI(model->buffers[i].uri)) {
|
!IsDataURI(model->buffers[i].uri)) {
|
||||||
binUri = model->buffers[i].uri;
|
binUri = model->buffers[i].uri;
|
||||||
|
if (!uri_cb.decode(binUri, &binFilename, uri_cb.user_data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
binUri = defaultBinFilename + defaultBinFileExt;
|
binFilename = defaultBinFilename + defaultBinFileExt;
|
||||||
bool inUse = true;
|
bool inUse = true;
|
||||||
int numUsed = 0;
|
int numUsed = 0;
|
||||||
while (inUse) {
|
while (inUse) {
|
||||||
inUse = false;
|
inUse = false;
|
||||||
for (const std::string &usedName : usedUris) {
|
for (const std::string &usedName : usedFilenames) {
|
||||||
if (binUri.compare(usedName) != 0) continue;
|
if (binFilename.compare(usedName) != 0) continue;
|
||||||
inUse = true;
|
inUse = true;
|
||||||
binUri = defaultBinFilename + std::to_string(numUsed++) +
|
binFilename = defaultBinFilename + std::to_string(numUsed++) +
|
||||||
defaultBinFileExt;
|
defaultBinFileExt;
|
||||||
break;
|
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);
|
usedFilenames.push_back(binFilename);
|
||||||
binSavePath = JoinPath(baseDir, binUri);
|
binSavePath = JoinPath(baseDir, binFilename);
|
||||||
if (!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
|
if (!SerializeGltfBuffer(model->buffers[i], buffer, binSavePath,
|
||||||
binUri)) {
|
binUri)) {
|
||||||
return false;
|
return false;
|
||||||
@ -7918,8 +8025,8 @@ bool TinyGLTF::WriteGltfSceneToFile(const Model *model,
|
|||||||
|
|
||||||
std::string uri;
|
std::string uri;
|
||||||
if (!UpdateImageObject(model->images[i], baseDir, int(i), embedImages,
|
if (!UpdateImageObject(model->images[i], baseDir, int(i), embedImages,
|
||||||
&this->WriteImageData, &uri,
|
&uri_cb, &this->WriteImageData,
|
||||||
this->write_image_user_data_)) {
|
this->write_image_user_data_, &uri)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SerializeGltfImage(model->images[i], uri, image);
|
SerializeGltfImage(model->images[i], uri, image);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user