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