Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "SPBitmap.h"
25 : #include "SPBytesView.h"
26 : #include "SPString.h"
27 : #include "SPBuffer.h"
28 : #include "SPLog.h"
29 : #include "SPFilesystem.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::bitmap {
32 :
33 : const BitmapFormat &getDefaultFormat(uint32_t);
34 : SPUNUSED static std::unique_lock<std::mutex> lockFormatList();
35 : SPUNUSED static void addCustomFormat(BitmapFormat &&fmt);
36 : SPUNUSED static const std::vector<BitmapFormat *> &getCustomFormats();
37 :
38 1177 : static Pair<FileFormat, StringView> _loadData(BitmapWriter &w, const uint8_t * data, size_t dataLen) {
39 1502 : for (int i = 0; i < toInt(FileFormat::Custom); ++i) {
40 1477 : auto &fmt = getDefaultFormat(i);
41 1477 : if (fmt.is(data, dataLen) && fmt.isReadable()) {
42 1152 : if (fmt.load(data, dataLen, w)) {
43 1152 : return pair(FileFormat(i), fmt.getName());
44 : }
45 : }
46 : }
47 :
48 25 : memory::vector<BitmapFormat *> fns;
49 :
50 25 : auto lock = lockFormatList();
51 :
52 25 : fns.reserve(getCustomFormats().size());
53 50 : for (auto &it : getCustomFormats()) {
54 25 : if (it->isReadable()) {
55 25 : fns.emplace_back(it);
56 : }
57 : }
58 :
59 25 : lock.unlock();
60 :
61 25 : for (auto &it : fns) {
62 25 : if (it->is(data, dataLen) && it->load(data, dataLen, w)) {
63 25 : return pair(FileFormat::Custom, it->getName());
64 : }
65 : }
66 :
67 0 : return pair(FileFormat::Custom, StringView());
68 25 : }
69 :
70 : struct BitmapPoolTarget {
71 : memory::PoolInterface::BytesType *bytes;
72 : const StrideFn *strideFn;
73 : };
74 :
75 : struct BitmapStdTarget {
76 : memory::StandartInterface::BytesType *bytes;
77 : const StrideFn *strideFn;
78 : };
79 :
80 1725 : static void _makeBitmapWriter(BitmapWriter &w, BitmapPoolTarget *target, BitmapTemplate<memory::PoolInterface> &bmp) {
81 1725 : w.target = target;
82 1725 : w.color = bmp.format();
83 1725 : w.alpha = bmp.alpha();
84 1725 : w.width = bmp.width();
85 1725 : w.height = bmp.height();
86 1725 : w.stride = bmp.stride();
87 :
88 1725 : if (target && target->strideFn) {
89 0 : w.getStride = [] (void *ptr, PixelFormat f, uint32_t w) {
90 0 : return (*((BitmapPoolTarget *)ptr)->strideFn)(f, w);
91 0 : };
92 0 : } else {
93 1725 : w.getStride = nullptr;
94 : }
95 :
96 6825 : w.push = [] (void *ptr, const uint8_t *data, uint32_t size) {
97 5100 : auto bytes = ((BitmapPoolTarget *)ptr)->bytes;
98 5100 : auto origSize = bytes->size();
99 5100 : bytes->resize(origSize + size);
100 5100 : memcpy(bytes->data() + origSize, data, size);
101 1725 : };
102 1950 : w.resize = [] (void *ptr, uint32_t size) {
103 225 : ((BitmapPoolTarget *)ptr)->bytes->resize(size);
104 1725 : };
105 28550 : w.getData = [] (void *ptr, uint32_t location) {
106 26825 : return ((BitmapPoolTarget *)ptr)->bytes->data() + location;
107 1725 : };
108 1750 : w.assign = [] (void *ptr, const uint8_t *data, uint32_t size) {
109 25 : auto bytes = ((BitmapPoolTarget *)ptr)->bytes;
110 25 : bytes->resize(size);
111 25 : memcpy(bytes->data(), data, size);
112 1725 : };
113 1725 : w.clear = [] (void *ptr) {
114 0 : ((BitmapPoolTarget *)ptr)->bytes->clear();
115 1725 : };
116 1725 : }
117 :
118 1628 : static void _makeBitmapWriter(BitmapWriter &w, BitmapStdTarget *target, BitmapTemplate<memory::StandartInterface> &bmp) {
119 1628 : w.target = target;
120 1628 : w.color = bmp.format();
121 1628 : w.alpha = bmp.alpha();
122 1628 : w.width = bmp.width();
123 1628 : w.height = bmp.height();
124 1628 : w.stride = bmp.stride();
125 :
126 1628 : if (target && target->strideFn) {
127 0 : w.getStride = [] (void *ptr, PixelFormat f, uint32_t w) {
128 0 : return (*((BitmapPoolTarget *)ptr)->strideFn)(f, w);
129 0 : };
130 0 : } else {
131 1628 : w.getStride = nullptr;
132 : }
133 :
134 9872 : w.push = [] (void *ptr, const uint8_t *data, uint32_t size) {
135 8244 : auto bytes = ((BitmapStdTarget *)ptr)->bytes;
136 8244 : auto origSize = bytes->size();
137 8244 : bytes->resize(origSize + size);
138 8244 : memcpy(bytes->data() + origSize, data, size);
139 1628 : };
140 2730 : w.resize = [] (void *ptr, uint32_t size) {
141 1102 : ((BitmapStdTarget *)ptr)->bytes->resize(size);
142 1628 : };
143 303330 : w.getData = [] (void *ptr, uint32_t location) {
144 301702 : return ((BitmapStdTarget *)ptr)->bytes->data() + location;
145 1628 : };
146 1703 : w.assign = [] (void *ptr, const uint8_t *data, uint32_t size) {
147 75 : auto bytes = ((BitmapStdTarget *)ptr)->bytes;
148 75 : bytes->resize(size);
149 75 : memcpy(bytes->data(), data, size);
150 1628 : };
151 1628 : w.clear = [] (void *ptr) {
152 0 : ((BitmapStdTarget *)ptr)->bytes->clear();
153 1628 : };
154 1628 : }
155 :
156 : template <>
157 175 : bool BitmapTemplate<memory::PoolInterface>::loadData(const uint8_t * data, size_t dataLen, const StrideFn &strideFn) {
158 175 : BitmapPoolTarget target { &_data, strideFn ? &strideFn : nullptr };
159 175 : BitmapWriter w;
160 175 : _makeBitmapWriter(w, &target, *this);
161 175 : auto ret = _loadData(w, data, dataLen);
162 175 : if (!ret.second.empty()) {
163 175 : _color = w.color;
164 175 : _alpha = w.alpha;
165 175 : _width = w.width;
166 175 : _height = w.height;
167 175 : _stride = w.stride;
168 175 : _originalFormat = ret.first;
169 175 : _originalFormatName = ret.second;
170 175 : return true;
171 : }
172 0 : return false;
173 : }
174 :
175 : template <>
176 1002 : bool BitmapTemplate<memory::StandartInterface>::loadData(const uint8_t * data, size_t dataLen, const StrideFn &strideFn) {
177 1002 : BitmapStdTarget target { &_data, strideFn ? &strideFn : nullptr };
178 1002 : BitmapWriter w;
179 1002 : _makeBitmapWriter(w, &target, *this);
180 1002 : auto ret = _loadData(w, data, dataLen);
181 1002 : if (!ret.second.empty()) {
182 1002 : _color = w.color;
183 1002 : _alpha = w.alpha;
184 1002 : _width = w.width;
185 1002 : _height = w.height;
186 1002 : _stride = w.stride;
187 1002 : _originalFormat = ret.first;
188 1002 : _originalFormatName = ret.second;
189 1002 : return true;
190 : }
191 0 : return false;
192 : }
193 :
194 : template <>
195 250 : bool BitmapTemplate<memory::StandartInterface>::save(FileFormat fmt, StringView path, bool invert) {
196 250 : BitmapWriter w;
197 250 : _makeBitmapWriter(w, nullptr, *this);
198 250 : auto &support = getDefaultFormat(toInt(fmt));
199 250 : if (support.isWritable()) {
200 250 : return support.save(path, _data.data(), w, invert);
201 : } else {
202 : // fallback to png
203 0 : return getDefaultFormat(toInt(FileFormat::Png))
204 0 : .save(path, _data.data(), w, invert);
205 : }
206 : return false;
207 : }
208 :
209 : template <>
210 1375 : bool BitmapTemplate<memory::PoolInterface>::save(FileFormat fmt, StringView path, bool invert) {
211 1375 : BitmapWriter w;
212 1375 : _makeBitmapWriter(w, nullptr, *this);
213 1375 : auto &support = getDefaultFormat(toInt(fmt));
214 1375 : if (support.isWritable()) {
215 1350 : return support.save(path, _data.data(), w, invert);
216 : } else {
217 : // fallback to png
218 50 : return getDefaultFormat(toInt(FileFormat::Png))
219 25 : .save(path, _data.data(), w, invert);
220 : }
221 : return false;
222 : }
223 :
224 : template <>
225 25 : bool BitmapTemplate<memory::StandartInterface>::save(StringView name, StringView path, bool invert) {
226 25 : BitmapFormat::save_fn fn = nullptr;
227 :
228 25 : auto lock = lockFormatList();
229 :
230 50 : for (auto &it : getCustomFormats()) {
231 25 : if (it->getName() == name && it->isWritable()) {
232 25 : fn = it->getSaveFn();
233 : }
234 : }
235 :
236 25 : lock.unlock();
237 :
238 25 : if (fn) {
239 25 : BitmapWriter w;
240 25 : _makeBitmapWriter(w, nullptr, *this);
241 25 : return fn(path, _data.data(), w, invert);
242 : }
243 0 : return false;
244 25 : }
245 :
246 : template <>
247 25 : bool BitmapTemplate<memory::PoolInterface>::save(StringView name, StringView path, bool invert) {
248 25 : BitmapFormat::save_fn fn = nullptr;
249 :
250 25 : auto lock = lockFormatList();
251 :
252 50 : for (auto &it : getCustomFormats()) {
253 25 : if (it->getName() == name && it->isWritable()) {
254 25 : fn = it->getSaveFn();
255 : }
256 : }
257 :
258 25 : lock.unlock();
259 :
260 25 : if (fn) {
261 25 : BitmapWriter w;
262 25 : _makeBitmapWriter(w, nullptr, *this);
263 25 : return fn(path, _data.data(), w, invert);
264 : }
265 0 : return false;
266 25 : }
267 :
268 : template <>
269 326 : auto BitmapTemplate<memory::StandartInterface>::write(FileFormat fmt, bool invert) -> memory::StandartInterface::BytesType {
270 326 : memory::StandartInterface::BytesType ret;
271 326 : BitmapStdTarget target { &ret, nullptr };
272 326 : BitmapWriter w;
273 326 : _makeBitmapWriter(w, &target, *this);
274 :
275 326 : auto &support = getDefaultFormat(toInt(fmt));
276 326 : if (support.isWritable() && support.write(_data.data(), w, invert)) {
277 276 : return ret;
278 50 : } else if (getDefaultFormat(toInt(FileFormat::Png)).write(_data.data(), w, invert)) {
279 50 : return ret;
280 : }
281 0 : return memory::StandartInterface::BytesType();
282 326 : }
283 :
284 : template <>
285 125 : auto BitmapTemplate<memory::PoolInterface>::write(FileFormat fmt, bool invert) -> memory::PoolInterface::BytesType {
286 125 : memory::PoolInterface::BytesType ret;
287 125 : BitmapPoolTarget target { &ret, nullptr };
288 125 : BitmapWriter w;
289 125 : _makeBitmapWriter(w, &target, *this);
290 :
291 125 : auto &support = getDefaultFormat(toInt(fmt));
292 125 : if (support.isWritable() && support.write(_data.data(), w, invert)) {
293 75 : return ret;
294 50 : } else if (getDefaultFormat(toInt(FileFormat::Png)).write(_data.data(), w, invert)) {
295 50 : return ret;
296 : }
297 0 : return memory::PoolInterface::BytesType();
298 125 : }
299 :
300 : template <>
301 25 : auto BitmapTemplate<memory::StandartInterface>::write(StringView name, bool invert) -> memory::StandartInterface::BytesType {
302 25 : BitmapFormat::write_fn fn = nullptr;
303 :
304 25 : auto lock = lockFormatList();
305 :
306 50 : for (auto &it : getCustomFormats()) {
307 25 : if (it->getName() == name && it->isWritable()) {
308 25 : fn = it->getWriteFn();
309 : }
310 : }
311 :
312 25 : lock.unlock();
313 :
314 25 : if (fn) {
315 25 : memory::StandartInterface::BytesType ret;
316 25 : BitmapStdTarget target { &ret, nullptr };
317 25 : BitmapWriter w;
318 25 : _makeBitmapWriter(w, &target, *this);
319 25 : if (fn(_data.data(), w, invert)) {
320 25 : return ret;
321 : }
322 25 : }
323 0 : return memory::StandartInterface::BytesType();
324 25 : }
325 :
326 : template <>
327 25 : auto BitmapTemplate<memory::PoolInterface>::write(StringView name, bool invert) -> memory::PoolInterface::BytesType {
328 25 : BitmapFormat::write_fn fn = nullptr;
329 :
330 25 : auto lock = lockFormatList();
331 :
332 50 : for (auto &it : getCustomFormats()) {
333 25 : if (it->getName() == name && it->isWritable()) {
334 25 : fn = it->getWriteFn();
335 : }
336 : }
337 :
338 25 : lock.unlock();
339 :
340 25 : if (fn) {
341 25 : memory::PoolInterface::BytesType ret;
342 25 : BitmapPoolTarget target { &ret, nullptr };
343 25 : BitmapWriter w;
344 25 : _makeBitmapWriter(w, &target, *this);
345 25 : if (fn(_data.data(), w, invert)) {
346 25 : return ret;
347 : }
348 25 : }
349 0 : return memory::PoolInterface::BytesType();
350 25 : }
351 :
352 : }
|