• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <core/image/intf_animated_image.h>
27 #include <core/image/intf_image_container.h>
28 #include <core/image/intf_image_loader_manager.h>
29 #include <core/io/intf_file.h>
30 #include <core/io/intf_file_manager.h>
31 #include <core/log.h>
32 #include <core/namespace.h>
33 #include <core/perf/cpu_perf_scope.h>
34 
35 CORE_BEGIN_NAMESPACE()
36 using BASE_NS::array_view;
37 using BASE_NS::make_unique;
38 using BASE_NS::move;
39 using BASE_NS::string_view;
40 using BASE_NS::unique_ptr;
41 using BASE_NS::vector;
42 
ImageLoaderManager(IFileManager & fileManager)43 ImageLoaderManager::ImageLoaderManager(IFileManager& fileManager) : fileManager_(fileManager)
44 {
45     for (const auto* typeInfo : GetPluginRegister().GetTypeInfos(IImageLoaderManager::ImageLoaderTypeInfo::UID)) {
46         if (typeInfo && (typeInfo->typeUid == IImageLoaderManager::ImageLoaderTypeInfo::UID)) {
47             const auto* imageLoaderInfo = static_cast<const IImageLoaderManager::ImageLoaderTypeInfo*>(typeInfo);
48             if (imageLoaderInfo->createLoader &&
49                 std::none_of(imageLoaders_.cbegin(), imageLoaders_.cend(),
50                     [&uid = imageLoaderInfo->uid](const RegisteredImageLoader& loader) { return loader.uid == uid; })) {
51                 imageLoaders_.push_back(
52                     { imageLoaderInfo->uid, imageLoaderInfo->createLoader(imageLoaderInfo->token) });
53             }
54         }
55     }
56     GetPluginRegister().AddListener(*this);
57 }
58 
~ImageLoaderManager()59 ImageLoaderManager::~ImageLoaderManager()
60 {
61     GetPluginRegister().RemoveListener(*this);
62 }
63 
RegisterImageLoader(IImageLoader::Ptr imageLoader)64 void ImageLoaderManager::RegisterImageLoader(IImageLoader::Ptr imageLoader)
65 {
66     if (!imageLoader) {
67         CORE_LOG_D("imageLoader is null, Not adding.");
68         return;
69     }
70 
71     // NOTE: We just add the registered unique pointers to a vector. The vector is not really used for anything else.
72     // And the loaders cannot be currently unregistered.
73     imageLoaders_.push_back({ {}, move(imageLoader) });
74 }
75 
LoadImage(const string_view uri,uint32_t loadFlags)76 ImageLoaderManager::LoadResult ImageLoaderManager::LoadImage(const string_view uri, uint32_t loadFlags)
77 {
78     CORE_CPU_PERF_SCOPE("CORE", "LoadImage()", uri, CORE_PROFILER_DEFAULT_COLOR);
79 
80     // Load 12 bytes (maximum header size of currently implemented file types)
81     IFile::Ptr file = fileManager_.OpenFile(uri);
82     if (!file) {
83         return ResultFailure("Can not open image.");
84     }
85 
86     return LoadImage(*file, loadFlags);
87 }
88 
LoadImage(IFile & file,uint32_t loadFlags)89 ImageLoaderManager::LoadResult ImageLoaderManager::LoadImage(IFile& file, uint32_t loadFlags)
90 {
91     CORE_CPU_PERF_SCOPE("CORE", "LoadImage(file)", "", CORE_PROFILER_DEFAULT_COLOR);
92 
93     const uint64_t byteLength = 12u;
94 
95     // Read header of the file to a buffer.
96     unique_ptr<uint8_t[]> buffer = make_unique<uint8_t[]>(static_cast<size_t>(byteLength));
97     const uint64_t read = file.Read(buffer.get(), byteLength);
98     if (read != byteLength) {
99         return ResultFailure("Can not read file header.");
100     }
101     file.Seek(0);
102 
103     for (auto& loader : imageLoaders_) {
104         if (loader.instance &&
105             loader.instance->CanLoad(array_view<const uint8_t>(buffer.get(), static_cast<size_t>(byteLength)))) {
106             return loader.instance->Load(file, loadFlags);
107         }
108     }
109     return ResultFailure("Image loader not found for this format.");
110 }
111 
LoadImage(array_view<const uint8_t> imageFileBytes,uint32_t loadFlags)112 ImageLoaderManager::LoadResult ImageLoaderManager::LoadImage(
113     array_view<const uint8_t> imageFileBytes, uint32_t loadFlags)
114 {
115     CORE_CPU_PERF_SCOPE("CORE", "LoadImage(bytes)", "", CORE_PROFILER_DEFAULT_COLOR);
116 
117     for (auto& loader : imageLoaders_) {
118         if (loader.instance && loader.instance->CanLoad(imageFileBytes)) {
119             return loader.instance->Load(imageFileBytes, loadFlags);
120         }
121     }
122 
123     return ResultFailure("Image loader not found for this format.");
124 }
125 
LoadAnimatedImage(const string_view uri,uint32_t loadFlags)126 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::LoadAnimatedImage(const string_view uri, uint32_t loadFlags)
127 {
128     CORE_CPU_PERF_SCOPE("CORE", "LoadAnimatedImage()", uri, CORE_PROFILER_DEFAULT_COLOR);
129 
130     // Load 12 bytes (maximum header size of currently implemented file types)
131     IFile::Ptr file = fileManager_.OpenFile(uri);
132     if (!file) {
133         return ResultFailureAnimated("Can not open image.");
134     }
135 
136     return LoadAnimatedImage(*file, loadFlags);
137 }
138 
LoadAnimatedImage(IFile & file,uint32_t loadFlags)139 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::LoadAnimatedImage(IFile& file, uint32_t loadFlags)
140 {
141     CORE_CPU_PERF_SCOPE("CORE", "LoadAnimatedImage(file)", "", CORE_PROFILER_DEFAULT_COLOR);
142 
143     const uint64_t byteLength = 12u;
144 
145     // Read header of the file to a buffer.
146     unique_ptr<uint8_t[]> buffer = make_unique<uint8_t[]>(static_cast<size_t>(byteLength));
147     const uint64_t read = file.Read(buffer.get(), byteLength);
148     if (read != byteLength) {
149         return ResultFailureAnimated("Can not read file header.");
150     }
151     file.Seek(0);
152 
153     for (auto& loader : imageLoaders_) {
154         if (loader.instance->CanLoad(array_view<const uint8_t>(buffer.get(), static_cast<size_t>(byteLength)))) {
155             return loader.instance->LoadAnimatedImage(file, loadFlags);
156         }
157     }
158     return ResultFailureAnimated("Image loader not found for this format.");
159 }
160 
LoadAnimatedImage(array_view<const uint8_t> imageFileBytes,uint32_t loadFlags)161 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::LoadAnimatedImage(
162     array_view<const uint8_t> imageFileBytes, uint32_t loadFlags)
163 {
164     CORE_CPU_PERF_SCOPE("CORE", "LoadAnimatedImage(bytes)", "", CORE_PROFILER_DEFAULT_COLOR);
165 
166     for (auto& loader : imageLoaders_) {
167         if (loader.instance->CanLoad(imageFileBytes)) {
168             return loader.instance->LoadAnimatedImage(imageFileBytes, loadFlags);
169         }
170     }
171 
172     return ResultFailureAnimated("Image loader not found for this format.");
173 }
174 
ResultFailure(const string_view error)175 ImageLoaderManager::LoadResult ImageLoaderManager::ResultFailure(const string_view error)
176 {
177     LoadResult result {
178         false,  // if success
179         "",     // array error[128];
180         nullptr // the image;
181     };
182 
183     // Copy the error string
184     const auto count = std::min(error.size(), sizeof(result.error) - 1);
185     error.copy(result.error, count);
186     result.error[count] = '\0';
187 
188     return result;
189 }
190 
ResultSuccess(IImageContainer::Ptr image)191 ImageLoaderManager::LoadResult ImageLoaderManager::ResultSuccess(IImageContainer::Ptr image)
192 {
193     return LoadResult {
194         true,       // if success
195         "",         // array error[128];
196         move(image) // the image;
197     };
198 }
199 
ResultFailureAnimated(const string_view error)200 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::ResultFailureAnimated(const string_view error)
201 {
202     LoadAnimatedResult result {
203         false,  // if success
204         "",     // array error[128];
205         nullptr // the image;
206     };
207 
208     // Copy the error string
209     const auto count = std::min(error.size(), sizeof(result.error) - 1);
210     error.copy(result.error, count);
211     result.error[count] = '\0';
212 
213     return result;
214 }
215 
ResultSuccessAnimated(IAnimatedImage::Ptr image)216 ImageLoaderManager::LoadAnimatedResult ImageLoaderManager::ResultSuccessAnimated(IAnimatedImage::Ptr image)
217 {
218     return LoadAnimatedResult {
219         true,       // if success
220         "",         // array error[128];
221         move(image) // the image;
222     };
223 }
224 
GetSupportedTypes() const225 vector<IImageLoaderManager::ImageType> ImageLoaderManager::GetSupportedTypes() const
226 {
227     vector<IImageLoaderManager::ImageType> allTypes;
228     for (const auto& loader : imageLoaders_) {
229         const auto types = loader.instance->GetSupportedTypes();
230         allTypes.append(types.cbegin(), types.cend());
231     }
232     return allTypes;
233 }
234 
OnTypeInfoEvent(EventType type,array_view<const ITypeInfo * const> typeInfos)235 void ImageLoaderManager::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
236 {
237     for (const auto* typeInfo : typeInfos) {
238         if (typeInfo && (typeInfo->typeUid == IImageLoaderManager::ImageLoaderTypeInfo::UID)) {
239             const auto* imageLoaderInfo = static_cast<const IImageLoaderManager::ImageLoaderTypeInfo*>(typeInfo);
240             if (type == EventType::ADDED) {
241                 if (imageLoaderInfo->createLoader &&
242                     std::none_of(imageLoaders_.cbegin(), imageLoaders_.cend(),
243                         [&uid = imageLoaderInfo->uid](
244                             const RegisteredImageLoader& loader) { return loader.uid == uid; })) {
245                     imageLoaders_.push_back(
246                         { imageLoaderInfo->uid, imageLoaderInfo->createLoader(imageLoaderInfo->token) });
247                 }
248             } else if (type == EventType::REMOVED) {
249                 imageLoaders_.erase(std::remove_if(imageLoaders_.begin(), imageLoaders_.end(),
250                     [&uid = imageLoaderInfo->uid](
251                         const RegisteredImageLoader& loader) { return loader.uid == uid; }),
252                     imageLoaders_.cend());
253             }
254         }
255     }
256 }
257 
258 CORE_END_NAMESPACE()
259