Texture size reduction on the fly for 3D model using metadata
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / load-scene-metadata.cpp
1 /*\r
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  * http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  *\r
16  */\r
17 \r
18 // INTERNAL INCLUDES\r
19 #include <dali-scene3d/internal/loader/gltf2-asset.h>\r
20 #include <dali-scene3d/internal/loader/json-reader.h>\r
21 #include <dali-scene3d/public-api/loader/load-scene-metadata.h>\r
22 #include <dali-scene3d/public-api/loader/utils.h>\r
23 \r
24 namespace js = json;\r
25 namespace gt = gltf2;\r
26 \r
27 namespace Dali::Scene3D::Loader\r
28 {\r
29 namespace\r
30 {\r
31 struct ImageData\r
32 {\r
33   struct SamplingMode\r
34   {\r
35     enum Type\r
36     {\r
37       INVALID          = -1,\r
38       BOX              = Dali::SamplingMode::BOX,\r
39       NEAREST          = Dali::SamplingMode::NEAREST,\r
40       LINEAR           = Dali::SamplingMode::LINEAR,\r
41       BOX_THEN_NEAREST = Dali::SamplingMode::BOX_THEN_NEAREST,\r
42       BOX_THEN_LINEAR  = Dali::SamplingMode::BOX_THEN_LINEAR,\r
43       NO_FILTER        = Dali::SamplingMode::NO_FILTER,\r
44       DONT_CARE        = Dali::SamplingMode::DONT_CARE\r
45     };\r
46 \r
47     static Type FromString(const char* s, size_t len);\r
48   };\r
49 \r
50   std::string mImageUri{};  ///< The URI of the image\r
51   uint16_t    mMinWidth{};  ///< The minimum width of the image\r
52   uint16_t    mMinHeight{}; ///< The mimimum height of the image\r
53 \r
54   ImageData::SamplingMode::Type mSamplingMode{ImageData::SamplingMode::BOX_THEN_LINEAR}; ///< The sampling mode used to resize the image.\r
55 };\r
56 \r
57 const std::map<std::string_view, ImageData::SamplingMode::Type> SAMPLING_MODE_TYPES{\r
58   ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX),\r
59   ENUM_STRING_MAPPING(ImageData::SamplingMode, NEAREST),\r
60   ENUM_STRING_MAPPING(ImageData::SamplingMode, LINEAR),\r
61   ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX_THEN_NEAREST),\r
62   ENUM_STRING_MAPPING(ImageData::SamplingMode, BOX_THEN_LINEAR),\r
63   ENUM_STRING_MAPPING(ImageData::SamplingMode, NO_FILTER),\r
64   ENUM_STRING_MAPPING(ImageData::SamplingMode, DONT_CARE),\r
65 };\r
66 \r
67 ENUM_TYPE_FROM_STRING(ImageData::SamplingMode, SAMPLING_MODE_TYPES)\r
68 \r
69 struct MetaData\r
70 {\r
71   std::vector<ImageData> mImageData;\r
72 };\r
73 \r
74 const auto IMAGE_METADATA_READER = std::move(js::Reader<ImageData>()\r
75                                                .Register(*js::MakeProperty("uri", js::Read::String, &ImageData::mImageUri))\r
76                                                .Register(*js::MakeProperty("minWidth", js::Read::Number, &ImageData::mMinWidth))\r
77                                                .Register(*js::MakeProperty("minHeight", js::Read::Number, &ImageData::mMinHeight))\r
78                                                .Register(*js::MakeProperty("samplingMode", gt::ReadStringEnum<ImageData::SamplingMode>, &ImageData::mSamplingMode)));\r
79 \r
80 const auto METADATA_READER = std::move(js::Reader<MetaData>()\r
81                                          .Register(*js::MakeProperty("images", js::Read::Array<ImageData, js::ObjectReader<ImageData>::Read>, &MetaData::mImageData)));\r
82 \r
83 } // namespace\r
84 \r
85 void LoadSceneMetadata(const std::string& url, SceneMetadata& sceneMetadata)\r
86 {\r
87   bool failed = false;\r
88   auto js     = LoadTextFile(url.c_str(), &failed);\r
89   if(failed)\r
90   {\r
91     return;\r
92   }\r
93 \r
94   json::unique_ptr root(json_parse(js.c_str(), js.size()));\r
95   if(!root)\r
96   {\r
97     throw std::runtime_error("Failed to parse " + url);\r
98   }\r
99   auto& rootObj = js::Cast<json_object_s>(*root);\r
100 \r
101   static bool setObjectReaders = true;\r
102   if(setObjectReaders)\r
103   {\r
104     js::SetObjectReader(IMAGE_METADATA_READER);\r
105 \r
106     setObjectReaders = false;\r
107   }\r
108 \r
109   MetaData metaData;\r
110   METADATA_READER.Read(rootObj, metaData);\r
111 \r
112   sceneMetadata.mImageMetadata.reserve(metaData.mImageData.size() + metaData.mImageData.size());\r
113   for(auto&& data : metaData.mImageData)\r
114   {\r
115     if(data.mSamplingMode == ImageData::SamplingMode::INVALID)\r
116     {\r
117       throw std::runtime_error("Sampling mode type unsupported.");\r
118     }\r
119     else\r
120     {\r
121       sceneMetadata.mImageMetadata.insert({data.mImageUri, ImageMetadata{ImageDimensions(data.mMinWidth, data.mMinHeight), static_cast<Dali::SamplingMode::Type>(data.mSamplingMode)}});\r
122     }\r
123   }\r
124 }\r
125 \r
126 } // namespace Dali::Scene3D::Loader\r