diff --git a/tiny_gltf.h b/tiny_gltf.h index f537e91..47ee59f 100644 --- a/tiny_gltf.h +++ b/tiny_gltf.h @@ -1662,73 +1662,71 @@ static bool ParseImage(Image *image, std::string *err, const json &o, LoadImageDataFunction *LoadImageData = nullptr, void *user_data = nullptr) { // A glTF image must either reference a bufferView or an image uri - double bufferView = -1; - bool isEmbedded = - ParseNumberProperty(&bufferView, err, o, "bufferView", false); - std::string uri; - std::string tmp_err; - if (!ParseStringProperty(&uri, &tmp_err, o, "uri", false) && !isEmbedded) { + // schema says oneOf [`bufferView`, `uri`] + // TODO(syoyo): Check the type of each parameters. + bool hasBufferView = (o.find("bufferView") != o.end()); + bool hasURI = (o.find("uri") != o.end()); + + if (hasBufferView && hasURI) { + // Should not both defined. if (err) { - (*err) += "`bufferView` or `uri` required for Image.\n"; + (*err) += "One of `bufferView` or `uri` should be defined, but both are defined for Image.\n"; + } + return false; + } + + if (!hasBufferView && !hasURI) { + if (err) { + (*err) += "Neither required `bufferView` nor `uri` defined for Image.\n"; } return false; } ParseStringProperty(&image->name, err, o, "name", false); + double bufferView = -1; + if (hasBufferView) { + if (!ParseNumberProperty(&bufferView, err, o, "bufferView", true)) { + if (err) { + (*err) += "Invalid `bufferView` definition for Image.\n"; + } + return false; + } + + std::string mime_type; + ParseStringProperty(&mime_type, err, o, "mimeType", false); + + double width = 0.0; + ParseNumberProperty(&width, err, o, "width", false); + + double height = 0.0; + ParseNumberProperty(&height, err, o, "height", false); + + // Just only save some information here. Loading actual image data from + // bufferView is done after this `ParseImage` function. + image->bufferView = static_cast(bufferView); + image->mimeType = mime_type; + image->width = static_cast(width); + image->height = static_cast(height); + + return true; + } + + std::string uri; + std::string tmp_err; + if (hasURI) { + if (!ParseStringProperty(&uri, &tmp_err, o, "uri", true)) { + if (err) { + (*err) += "`bufferView` or `uri` required for Image.\n"; + } + return false; + } + } + std::vector img; - if (is_binary) { - // Still binary glTF accepts external dataURI. First try external resources. - bool loaded = false; - if (IsDataURI(uri)) { - loaded = DecodeDataURI(&img, uri, 0, false); - } else { - // Assume external file - // Keep texture path (for textures that cannot be decoded) - image->uri = uri; -#ifdef TINYGLTF_NO_EXTERNAL_IMAGE - return true; -#endif - loaded = LoadExternalFile(&img, err, uri, basedir, 0, false); - } - - if (!loaded) { - // load data from (embedded) binary data - - if ((bin_size == 0) || (bin_data == nullptr)) { - if (err) { - (*err) += "Invalid binary data.\n"; - } - return false; - } - - double buffer_view = -1.0; - if (!ParseNumberProperty(&buffer_view, err, o, "bufferView", true, - "Image")) { - return false; - } - - std::string mime_type; - ParseStringProperty(&mime_type, err, o, "mimeType", false); - - double width = 0.0; - ParseNumberProperty(&width, err, o, "width", false); - - double height = 0.0; - ParseNumberProperty(&height, err, o, "height", false); - - // Just only save some information here. Loading actual image data from - // bufferView is done in other place. - image->bufferView = static_cast(buffer_view); - image->mimeType = mime_type; - image->width = static_cast(width); - image->height = static_cast(height); - - return true; - } - } else { + if (hasURI) { if (IsDataURI(uri)) { if (!DecodeDataURI(&img, uri, 0, false)) { if (err) { @@ -1750,6 +1748,7 @@ static bool ParseImage(Image *image, std::string *err, const json &o, // If the image cannot be loaded, keep uri as image->uri. return true; } + if (img.empty()) { if (err) { (*err) += "Image is empty.\n";