1 /*
2 * Copyright (C) 2023 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 rowPointers = (T **)malloc(height * sizeof(T *));
106 allocHeight = static_cast<int>(height);
107
108 size_t rowbytes = width * channels * channelSize;
109 if (rowbytes <= 0 || rowbytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
110 allocSucc = false;
111 return;
112 }
113 for (int i = 0; i < allocHeight; i++) {
114 rowPointers[i] = nullptr; /* security precaution */
115 }
116 for (int i = 0; i < allocHeight; i++) {
117 rowPointers[i] = (T *)malloc(rowbytes);
118 }
119 allocSucc = true;
120 }
121
~RowPointers()122 ~RowPointers()
123 {
124 if (rowPointers) {
125 for (int i = 0; i < allocHeight; i++) {
126 if (rowPointers[i]) {
127 free(rowPointers[i]);
128 }
129 }
130 free(rowPointers);
131 }
132 }
133 };
134
135 template <typename T>
136 class ArrayLoader {
137 public:
ArrayLoader(BASE_NS::array_view<const T> imageFileBytes)138 ArrayLoader(BASE_NS::array_view<const T> imageFileBytes)
139 {
140 buf = imageFileBytes;
141 arrSize = imageFileBytes.size();
142 curr = 0;
143 }
ArrayRead(T * dest,uint64_t length)144 void ArrayRead(T *dest, uint64_t length)
145 {
146 if (curr + length > arrSize) {
147 CORE_LOG_E("ArrayLoader out of range.");
148 return;
149 }
150 int ret = memcpy_s(dest, length, static_cast<const T *>(buf.data()) + curr, length);
151 if (ret != 0) {
152 CORE_LOG_E("memcpy_s in ArrayLoader error.");
153 return;
154 }
155 curr += length;
156 }
157
158 private:
159 BASE_NS::array_view<const T> buf;
160 uint64_t curr;
161 uint64_t arrSize;
162 };
163
164 template <typename T>
VerticalFlipRowPointers(T ** rowPointers,uint32_t height,uint32_t width,uint32_t channels)165 void VerticalFlipRowPointers(T **rowPointers, uint32_t height, uint32_t width, uint32_t channels)
166 {
167 uint32_t halfWidth = width / 2;
168 for (uint32_t y = 0; y < height; y++) {
169 for (uint32_t x = 0; x < halfWidth; x++) {
170 for (uint32_t k = 0; k < channels; k++) {
171 uint32_t idx = x * channels + k;
172 uint32_t ridx = (width - x - 1) * channels + k;
173 T tempPixel = rowPointers[y][idx];
174 rowPointers[y][idx] = rowPointers[y][ridx];
175 rowPointers[y][ridx] = tempPixel;
176 }
177 }
178 }
179 }
180
181 template <typename T>
VerticalFlipRow(T * rowPointer,uint32_t width,uint32_t channels)182 void VerticalFlipRow(T *rowPointer, uint32_t width, uint32_t channels)
183 {
184 uint32_t halfWidth = width / 2;
185 for (uint32_t x = 0; x < halfWidth; x++) {
186 for (uint32_t k = 0; k < channels; k++) {
187 uint32_t idx = x * channels + k;
188 uint32_t ridx = (width - x - 1) * channels + k;
189 T tempPixel = rowPointer[idx];
190 rowPointer[idx] = rowPointer[ridx];
191 rowPointer[ridx] = tempPixel;
192 }
193 }
194 }
195
196 CORE_END_NAMESPACE()
197
198 #endif // CORE_IMAGE_LOADERS_IMAGE_LOADER_COMMON_H