1 /*
2 * Copyright (C) 2023-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 #ifndef CORE_IMAGE_LOADERS_IMAGE_LOADER_COMMON_H
17 #define CORE_IMAGE_LOADERS_IMAGE_LOADER_COMMON_H
18
19 #include <functional>
20 #include <limits>
21 #include <base/math/mathf.h>
22 #include <core/io/intf_file_manager.h>
23 #include <core/log.h>
24 #include <core/namespace.h>
25
26 #include "image/image_loader_manager.h"
27
CORE_BEGIN_NAMESPACE()28 CORE_BEGIN_NAMESPACE()
29
30 class ImageLoaderCommon {
31 public:
32 static ImageLoaderCommon &GetInstance();
33
34 bool PremultiplyAlpha(uint8_t *imageBytes, uint32_t width, uint32_t height, uint32_t channelCount,
35 uint32_t bytesPerChannel, bool linear);
36
37 private:
38 ImageLoaderCommon() = default;
39 ~ImageLoaderCommon() = default;
40
41 ImageLoaderCommon(const ImageLoaderCommon &imgLoaderCommon) = delete;
42 const ImageLoaderCommon &operator=(const ImageLoaderCommon &imgLoaderCommon) = delete;
43
44 void InitializeSRGBTable();
45
46 uint8_t SRGBPremultiplyLookup[256u * 256u] = {0};
47 };
48
49 void FreeLibBaseImageBytes(void *imageBytes);
50
51 using LibBaseImageDeleter = std::function<void(void *)>;
52 using LibBaseImagePtr = BASE_NS::unique_ptr<void, LibBaseImageDeleter>;
53
54 class LibBaseImage : public IImageContainer {
55 public:
56 LibBaseImage();
57
58 virtual ~LibBaseImage() = default;
59
60 using Ptr = BASE_NS::unique_ptr<LibBaseImage, Deleter>;
61
62 const ImageDesc &GetImageDesc() const override;
63
64 BASE_NS::array_view<const uint8_t> GetData() const override;
65
66 BASE_NS::array_view<const SubImageDesc> GetBufferImageCopies() const override;
67
68 static constexpr BASE_NS::Format ResolveFormat(uint32_t loadFlags, uint32_t componentCount, bool is16bpc);
69
70 constexpr static ImageDesc ResolveImageDesc(BASE_NS::Format format, uint32_t imageWidth, uint32_t imageHeight,
71 uint32_t bitsPerPixel, bool generateMips, bool isPremultiplied);
72
73 static ImageLoaderManager::LoadResult CreateImage(LibBaseImagePtr imageBytes, uint32_t imageWidth,
74 uint32_t imageHeight, uint32_t componentCount, uint32_t loadFlags, bool is16bpc);
75
76 struct Info {
77 uint32_t width;
78 uint32_t height;
79 uint32_t componentCount;
80 bool is16bpc;
81 };
82
83 protected:
84 virtual void Destroy() override;
85 ImageDesc imageDesc_;
86 SubImageDesc imageBuffer_;
87
88 LibBaseImagePtr imageBytes_;
89 size_t imageBytesLength_ = 0;
90 };
91
92 template <typename T>
93 class RowPointers {
94 public:
95 T **rowPointers = nullptr;
96 int allocHeight = 0;
97 bool allocSucc = false;
98
RowPointers(uint32_t width,uint32_t height,uint32_t channels,uint32_t channelSize)99 RowPointers(uint32_t width, uint32_t height, uint32_t channels, uint32_t channelSize)
100 {
101 if (height <= 0 || height > static_cast<size_t>(std::numeric_limits<int>::max())) {
102 allocSucc = false;
103 return;
104 }
105 size_t rowbytes = static_cast<size_t>(width * channels) * channelSize;
106 if (rowbytes <= 0 || rowbytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
107 allocSucc = false;
108 return;
109 }
110 rowPointers = (T **)malloc(height * sizeof(T *));
111 if (rowPointers == nullptr) {
112 CORE_LOG_E("malloc fail return null");
113 return;
114 }
115 allocHeight = static_cast<int>(height);
116 for (int i = 0; i < allocHeight; i++) {
117 rowPointers[i] = nullptr; /* security precaution */
118 }
119 for (int i = 0; i < allocHeight; i++) {
120 rowPointers[i] = (T *)malloc(rowbytes);
121 if (rowPointers[i] == nullptr) {
122 CORE_LOG_E("malloc fail return null");
123 return;
124 }
125 }
126 allocSucc = true;
127 }
128
~RowPointers()129 ~RowPointers()
130 {
131 if (rowPointers) {
132 for (int i = 0; i < allocHeight; i++) {
133 if (rowPointers[i]) {
134 free(rowPointers[i]);
135 }
136 }
137 free(rowPointers);
138 }
139 }
140 };
141
142 template <typename T>
143 class ArrayLoader {
144 public:
ArrayLoader(BASE_NS::array_view<const T> imageFileBytes)145 ArrayLoader(BASE_NS::array_view<const T> imageFileBytes)
146 {
147 buf = imageFileBytes;
148 arrSize = imageFileBytes.size();
149 curr = 0;
150 }
ArrayRead(T * dest,uint64_t length)151 void ArrayRead(T *dest, uint64_t length)
152 {
153 if (curr + length > arrSize) {
154 CORE_LOG_E("ArrayLoader out of range.");
155 return;
156 }
157 int ret = memcpy_s(dest, length, static_cast<const T *>(buf.data()) + curr, length);
158 if (ret != 0) {
159 CORE_LOG_E("memcpy_s in ArrayLoader error.");
160 return;
161 }
162 curr += length;
163 }
164
165 private:
166 BASE_NS::array_view<const T> buf;
167 uint64_t curr;
168 uint64_t arrSize;
169 };
170
171 template <typename T>
VerticalFlipRowPointers(T ** rowPointers,uint32_t height,uint32_t width,uint32_t channels)172 void VerticalFlipRowPointers(T **rowPointers, uint32_t height, uint32_t width, uint32_t channels)
173 {
174 uint32_t halfWidth = width / 2;
175 for (uint32_t y = 0; y < height; y++) {
176 for (uint32_t x = 0; x < halfWidth; x++) {
177 for (uint32_t k = 0; k < channels; k++) {
178 uint32_t idx = x * channels + k;
179 uint32_t ridx = (width - x - 1) * channels + k;
180 T tempPixel = rowPointers[y][idx];
181 rowPointers[y][idx] = rowPointers[y][ridx];
182 rowPointers[y][ridx] = tempPixel;
183 }
184 }
185 }
186 }
187
188 template <typename T>
VerticalFlipRow(T * rowPointer,uint32_t width,uint32_t channels)189 void VerticalFlipRow(T *rowPointer, uint32_t width, uint32_t channels)
190 {
191 uint32_t halfWidth = width / 2;
192 for (uint32_t x = 0; x < halfWidth; x++) {
193 for (uint32_t k = 0; k < channels; k++) {
194 uint32_t idx = x * channels + k;
195 uint32_t ridx = (width - x - 1) * channels + k;
196 T tempPixel = rowPointer[idx];
197 rowPointer[idx] = rowPointer[ridx];
198 rowPointer[ridx] = tempPixel;
199 }
200 }
201 }
202
203 CORE_END_NAMESPACE()
204
205 #endif // CORE_IMAGE_LOADERS_IMAGE_LOADER_COMMON_H