1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "image_loader_manager.h"
17
18 #include <algorithm>
19
20 #include <base/containers/array_view.h>
21 #include <base/containers/string_view.h>
22 #include <base/containers/type_traits.h>
23 #include <base/containers/unique_ptr.h>
24 #include <base/containers/vector.h>
25 #include <base/namespace.h>
26 #include <base/util/uid_util.h>
27 #include <core/image/intf_animated_image.h>
28 #include <core/image/intf_image_container.h>
29 #include <core/image/intf_image_loader_manager.h>
30 #include <core/io/intf_file.h>
31 #include <core/io/intf_file_manager.h>
32 #include <core/log.h>
33 #include <core/namespace.h>
34 #include <core/perf/cpu_perf_scope.h>
35
36 CORE_BEGIN_NAMESPACE()
37 using BASE_NS::array_view;
38 using BASE_NS::make_unique;
39 using BASE_NS::move;
40 using BASE_NS::string_view;
41 using BASE_NS::unique_ptr;
42 using BASE_NS::vector;
43
ImageLoaderManager(IFileManager & fileManager)44 ImageLoaderManager::ImageLoaderManager(IFileManager& fileManager) : fileManager_(fileManager)
45 {
46 for (const auto* typeInfo : GetPluginRegister().GetTypeInfos(IImageLoaderManager::ImageLoaderTypeInfo::UID)) {
47 if (typeInfo && (typeInfo->typeUid == IImageLoaderManager::ImageLoaderTypeInfo::UID)) {
48 const auto* imageLoaderInfo = static_cast<const IImageLoaderManager::ImageLoaderTypeInfo*>(typeInfo);
49 if (imageLoaderInfo->createLoader &&
50 std::none_of(imageLoaders_.cbegin(), imageLoaders_.cend(),
51 [&uid = imageLoaderInfo->uid](const RegisteredImageLoader& loader) { return loader.uid == uid; })) {
52 imageLoaders_.push_back(
53 { imageLoaderInfo->uid, imageLoaderInfo->createLoader(imageLoaderInfo->token) });
54 }
55 }
56 }
57 GetPluginRegister().AddListener(*this);
58 }
59
~ImageLoaderManager()60 ImageLoaderManager::~ImageLoaderManager()
61 {
62 GetPluginRegister().RemoveListener(*this);
63 }
64
RegisterImageLoader(IImageLoader::Ptr imageLoader)65 void ImageLoaderManager::RegisterImageLoader(IImageLoader::Ptr imageLoader)
66 {
67 if (!imageLoader) {
68 CORE_LOG_D("imageLoader is null, Not adding.");
69 return;
70 }
71
72 // NOTE: We just add the registered unique pointers to a vector. The vector is not really used for anything else.
73 // And the loaders cannot be currently unregistered.
74 imageLoaders_.push_back({ {}, move(imageLoader) });
75 }
76
LoadImage(const string_view uri,uint32_t loadFlags)77 ImageLoaderManager::LoadResult ImageLoaderManager::LoadImage(const string_view uri, uint32_t loadFlags)
78 {
79 CORE_CPU_PERF_SCOPE("CORE", "LoadImage()", uri, CORE_PROFILER_DEFAULT_COLOR);
80
81 // Load 12 bytes (maximum header size of currently implemented file types)
82 IFile::Ptr file = fileManager_.OpenFile(uri);
83 if (!file) {
84 return ResultFailure("Can not open image.");
85 }
86
87 return LoadImage(*file, loadFlags);
88 }
89
LoadImage(IFile & file,uint32_t loadFlags)90 ImageLoaderManager::LoadResult ImageLoaderManager::LoadImage(IFile& file, uint32_t loadFlags)
91 {
92 CORE_CPU_PERF_SCOPE("CORE", "LoadImage(file)", "", CORE_PROFILER_DEFAULT_COLOR);
93
94 const uint64_t byteLength = 12u;
95
96 // Read header of the file to a buffer.
97 unique_ptr<uint8_t[]> buffer = make_unique<uint8_t[]>(static_cast<size_t>(byteLength));
98 const uint64_t read = file.Read(buffer.get(), byteLength);
99 if (read != byteLength) {
100 return ResultFailure("Can not read file header.");
101 }
102 file.Seek(0);
103
104 for (auto& loader : imageLoaders_) {
105 if (loader.instance &&
106 loader.instance->CanLoad(array_view<const uint8_t>(buffer.get(), static_cast<size_t>(byteLength)))) {
107 return loader.instance->Load(file, loadFlags);
108 }
109 }
110 return ResultFailure("Image loader not found for this format.");
111 }
112
LoadImage(array_view<const uint8_t> imageFileBytes,uint32_t loadFlags)113 ImageLoaderManager::LoadResult ImageLoaderManager::LoadImage(
114 array_view<const uint8_t> imageFileBytes, uint32_t loadFlags)
115 {
116 CORE_CPU_PERF_SCOPE("CORE", "LoadImage(bytes)", "", CORE_PROFILER_DEFAULT_COLOR);
117
118 for (auto& loader : imageLoaders_) {
119 if (loader.instance && loader.instance->CanLoad(imageFileBytes)) {
120 return loader.instance->Load(imageFileBytes, loadFlags);
121 }
122 }
123
124 return ResultFailure("Image loader not found for this format.");
125 }
126
LoadAnimatedImage(const string_view uri,uint32_t loadFlags)127 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::LoadAnimatedImage(const string_view uri, uint32_t loadFlags)
128 {
129 CORE_CPU_PERF_SCOPE("CORE", "LoadAnimatedImage()", uri, CORE_PROFILER_DEFAULT_COLOR);
130
131 // Load 12 bytes (maximum header size of currently implemented file types)
132 IFile::Ptr file = fileManager_.OpenFile(uri);
133 if (!file) {
134 return ResultFailureAnimated("Can not open image.");
135 }
136
137 return LoadAnimatedImage(*file, loadFlags);
138 }
139
LoadAnimatedImage(IFile & file,uint32_t loadFlags)140 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::LoadAnimatedImage(IFile& file, uint32_t loadFlags)
141 {
142 CORE_CPU_PERF_SCOPE("CORE", "LoadAnimatedImage(file)", "", CORE_PROFILER_DEFAULT_COLOR);
143
144 const uint64_t byteLength = 12u;
145
146 // Read header of the file to a buffer.
147 unique_ptr<uint8_t[]> buffer = make_unique<uint8_t[]>(static_cast<size_t>(byteLength));
148 const uint64_t read = file.Read(buffer.get(), byteLength);
149 if (read != byteLength) {
150 return ResultFailureAnimated("Can not read file header.");
151 }
152 file.Seek(0);
153
154 for (auto& loader : imageLoaders_) {
155 if (loader.instance &&
156 loader.instance->CanLoad(array_view<const uint8_t>(buffer.get(), static_cast<size_t>(byteLength)))) {
157 return loader.instance->LoadAnimatedImage(file, loadFlags);
158 }
159 }
160 return ResultFailureAnimated("Image loader not found for this format.");
161 }
162
LoadAnimatedImage(array_view<const uint8_t> imageFileBytes,uint32_t loadFlags)163 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::LoadAnimatedImage(
164 array_view<const uint8_t> imageFileBytes, uint32_t loadFlags)
165 {
166 CORE_CPU_PERF_SCOPE("CORE", "LoadAnimatedImage(bytes)", "", CORE_PROFILER_DEFAULT_COLOR);
167
168 for (auto& loader : imageLoaders_) {
169 if (loader.instance && loader.instance->CanLoad(imageFileBytes)) {
170 return loader.instance->LoadAnimatedImage(imageFileBytes, loadFlags);
171 }
172 }
173
174 return ResultFailureAnimated("Image loader not found for this format.");
175 }
176
ResultFailure(const string_view error)177 ImageLoaderManager::LoadResult ImageLoaderManager::ResultFailure(const string_view error)
178 {
179 LoadResult result {
180 false, // if success
181 "", // array error[128];
182 nullptr // the image;
183 };
184
185 // Copy the error string
186 const auto count = std::min(error.size(), sizeof(result.error) - 1);
187 error.copy(result.error, count);
188 result.error[count] = '\0';
189
190 return result;
191 }
192
ResultSuccess(IImageContainer::Ptr image)193 ImageLoaderManager::LoadResult ImageLoaderManager::ResultSuccess(IImageContainer::Ptr image)
194 {
195 return LoadResult {
196 true, // if success
197 "", // array error[128];
198 move(image) // the image;
199 };
200 }
201
ResultFailureAnimated(const string_view error)202 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::ResultFailureAnimated(const string_view error)
203 {
204 LoadAnimatedResult result {
205 false, // if success
206 "", // array error[128];
207 nullptr // the image;
208 };
209
210 // Copy the error string
211 const auto count = std::min(error.size(), sizeof(result.error) - 1);
212 error.copy(result.error, count);
213 result.error[count] = '\0';
214
215 return result;
216 }
217
ResultSuccessAnimated(IAnimatedImage::Ptr image)218 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::ResultSuccessAnimated(IAnimatedImage::Ptr image)
219 {
220 return LoadAnimatedResult {
221 true, // if success
222 "", // array error[128];
223 move(image) // the image;
224 };
225 }
226
GetSupportedTypes() const227 vector<IImageLoaderManager::ImageType> ImageLoaderManager::GetSupportedTypes() const
228 {
229 vector<IImageLoaderManager::ImageType> allTypes;
230 for (const auto& loader : imageLoaders_) {
231 if (loader.instance) {
232 const auto types = loader.instance->GetSupportedTypes();
233 allTypes.append(types.cbegin(), types.cend());
234 } else {
235 CORE_LOG_E(" loader.instance is nullptr and uid: %s", to_string(loader.uid).data());
236 }
237 }
238 return allTypes;
239 }
240
OnTypeInfoEvent(EventType type,array_view<const ITypeInfo * const> typeInfos)241 void ImageLoaderManager::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
242 {
243 for (const auto* typeInfo : typeInfos) {
244 if (typeInfo && (typeInfo->typeUid == IImageLoaderManager::ImageLoaderTypeInfo::UID)) {
245 const auto* imageLoaderInfo = static_cast<const IImageLoaderManager::ImageLoaderTypeInfo*>(typeInfo);
246 if (type == EventType::ADDED) {
247 if (imageLoaderInfo->createLoader &&
248 std::none_of(imageLoaders_.cbegin(), imageLoaders_.cend(),
249 [&uid = imageLoaderInfo->uid](
250 const RegisteredImageLoader& loader) { return loader.uid == uid; })) {
251 imageLoaders_.push_back(
252 { imageLoaderInfo->uid, imageLoaderInfo->createLoader(imageLoaderInfo->token) });
253 }
254 } else if (type == EventType::REMOVED) {
255 imageLoaders_.erase(std::remove_if(imageLoaders_.begin(), imageLoaders_.end(),
256 [&uid = imageLoaderInfo->uid](const RegisteredImageLoader &loader) {
257 return loader.uid == uid;
258 }),
259 imageLoaders_.cend());
260 }
261 }
262 }
263 }
264
265 CORE_END_NAMESPACE()
266