1 | // [Blend2D] |
2 | // 2D Vector Graphics Powered by a JIT Compiler. |
3 | // |
4 | // [License] |
5 | // Zlib - See LICENSE.md file in the package. |
6 | |
7 | #ifndef BLEND2D_BLIMAGE_H |
8 | #define BLEND2D_BLIMAGE_H |
9 | |
10 | #include "./blarray.h" |
11 | #include "./blformat.h" |
12 | #include "./blgeometry.h" |
13 | #include "./blvariant.h" |
14 | |
15 | //! \addtogroup blend2d_api_imaging |
16 | //! \{ |
17 | |
18 | // ============================================================================ |
19 | // [Constants] |
20 | // ============================================================================ |
21 | |
22 | //! Image codec feature bits. |
23 | BL_DEFINE_ENUM(BLImageCodecFeatures) { |
24 | //! Image codec supports reading images (can create BLImageDecoder). |
25 | BL_IMAGE_CODEC_FEATURE_READ = 0x00000001u, |
26 | //! Image codec supports writing images (can create BLImageEncoder). |
27 | BL_IMAGE_CODEC_FEATURE_WRITE = 0x00000002u, |
28 | //! Image codec supports lossless compression. |
29 | BL_IMAGE_CODEC_FEATURE_LOSSLESS = 0x00000004u, |
30 | //! Image codec supports loosy compression. |
31 | BL_IMAGE_CODEC_FEATURE_LOSSY = 0x00000008u, |
32 | //! Image codec supports writing multiple frames (GIF). |
33 | BL_IMAGE_CODEC_FEATURE_MULTI_FRAME = 0x00000010u, |
34 | //! Image codec supports IPTC metadata. |
35 | BL_IMAGE_CODEC_FEATURE_IPTC = 0x10000000u, |
36 | //! Image codec supports EXIF metadata. |
37 | BL_IMAGE_CODEC_FEATURE_EXIF = 0x20000000u, |
38 | //! Image codec supports XMP metadata. |
39 | BL_IMAGE_CODEC_FEATURE_XMP = 0x40000000u |
40 | }; |
41 | |
42 | //! Flags used by `BLImageInfo`. |
43 | BL_DEFINE_ENUM(BLImageInfoFlags) { |
44 | //! Progressive mode. |
45 | BL_IMAGE_INFO_FLAG_PROGRESSIVE = 0x00000001u |
46 | }; |
47 | |
48 | //! Filter type used by `BLImage::scale()`. |
49 | BL_DEFINE_ENUM(BLImageScaleFilter) { |
50 | //! No filter or uninitialized. |
51 | BL_IMAGE_SCALE_FILTER_NONE = 0, |
52 | //! Nearest neighbor filter (radius 1.0). |
53 | BL_IMAGE_SCALE_FILTER_NEAREST = 1, |
54 | //! Bilinear filter (radius 1.0). |
55 | BL_IMAGE_SCALE_FILTER_BILINEAR = 2, |
56 | //! Bicubic filter (radius 2.0). |
57 | BL_IMAGE_SCALE_FILTER_BICUBIC = 3, |
58 | //! Bell filter (radius 1.5). |
59 | BL_IMAGE_SCALE_FILTER_BELL = 4, |
60 | //! Gauss filter (radius 2.0). |
61 | BL_IMAGE_SCALE_FILTER_GAUSS = 5, |
62 | //! Hermite filter (radius 1.0). |
63 | BL_IMAGE_SCALE_FILTER_HERMITE = 6, |
64 | //! Hanning filter (radius 1.0). |
65 | BL_IMAGE_SCALE_FILTER_HANNING = 7, |
66 | //! Catrom filter (radius 2.0). |
67 | BL_IMAGE_SCALE_FILTER_CATROM = 8, |
68 | //! Bessel filter (radius 3.2383). |
69 | BL_IMAGE_SCALE_FILTER_BESSEL = 9, |
70 | //! Sinc filter (radius 2.0, adjustable through `BLImageScaleOptions`). |
71 | BL_IMAGE_SCALE_FILTER_SINC = 10, |
72 | //! Lanczos filter (radius 2.0, adjustable through `BLImageScaleOptions`). |
73 | BL_IMAGE_SCALE_FILTER_LANCZOS = 11, |
74 | //! Blackman filter (radius 2.0, adjustable through `BLImageScaleOptions`). |
75 | BL_IMAGE_SCALE_FILTER_BLACKMAN = 12, |
76 | //! Mitchell filter (radius 2.0, parameters 'b' and 'c' passed through `BLImageScaleOptions`). |
77 | BL_IMAGE_SCALE_FILTER_MITCHELL = 13, |
78 | //! Filter using a user-function, must be passed through `BLImageScaleOptions`. |
79 | BL_IMAGE_SCALE_FILTER_USER = 14, |
80 | |
81 | //! Count of image-scale filters. |
82 | BL_IMAGE_SCALE_FILTER_COUNT = 15 |
83 | }; |
84 | |
85 | // ============================================================================ |
86 | // [Typedefs] |
87 | // ============================================================================ |
88 | |
89 | //! A user function that can be used by `BLImage::scale()`. |
90 | typedef BLResult (BL_CDECL* BLImageScaleUserFunc)(double* dst, const double* tArray, size_t n, const void* data) BL_NOEXCEPT; |
91 | |
92 | // ============================================================================ |
93 | // [BLImageData] |
94 | // ============================================================================ |
95 | |
96 | //! Data that describes a raster image. Used by `BLImage`. |
97 | struct BLImageData { |
98 | void* pixelData; |
99 | intptr_t stride; |
100 | BLSizeI size; |
101 | uint32_t format; |
102 | uint32_t flags; |
103 | |
104 | // -------------------------------------------------------------------------- |
105 | #ifdef __cplusplus |
106 | |
107 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
108 | |
109 | #endif |
110 | // -------------------------------------------------------------------------- |
111 | }; |
112 | |
113 | // ============================================================================ |
114 | // [BLImageInfo] |
115 | // ============================================================================ |
116 | |
117 | //! Image information provided by image codecs. |
118 | struct BLImageInfo { |
119 | //! Image size. |
120 | BLSizeI size; |
121 | //! Pixel density per one meter, can contain fractions. |
122 | BLSize density; |
123 | |
124 | //! Image flags. |
125 | uint32_t flags; |
126 | //! Image depth. |
127 | uint16_t depth; |
128 | //! Number of planes. |
129 | uint16_t planeCount; |
130 | //! Number of frames (0 = unknown/unspecified). |
131 | uint64_t frameCount; |
132 | |
133 | //! Image format (as understood by codec). |
134 | char format[16]; |
135 | //! Image compression (as understood by codec). |
136 | char compression[16]; |
137 | |
138 | // -------------------------------------------------------------------------- |
139 | #ifdef __cplusplus |
140 | |
141 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
142 | |
143 | #endif |
144 | // -------------------------------------------------------------------------- |
145 | }; |
146 | |
147 | // ============================================================================ |
148 | // [BLImageScaleOptions] |
149 | // ============================================================================ |
150 | |
151 | //! Options that can used to customize image scaling. |
152 | struct BLImageScaleOptions { |
153 | BLImageScaleUserFunc userFunc; |
154 | void* userData; |
155 | |
156 | double radius; |
157 | union { |
158 | double data[3]; |
159 | struct { |
160 | double b, c; |
161 | } mitchell; |
162 | }; |
163 | |
164 | // -------------------------------------------------------------------------- |
165 | #ifdef __cplusplus |
166 | |
167 | BL_INLINE void reset() noexcept { memset(this, 0, sizeof(*this)); } |
168 | |
169 | BL_INLINE void resetToDefaults() noexcept { |
170 | userFunc = nullptr; |
171 | userData = nullptr; |
172 | radius = 2.0; |
173 | mitchell.b = 1.0 / 3.0; |
174 | mitchell.c = 1.0 / 3.0; |
175 | data[2] = 0.0; |
176 | } |
177 | |
178 | #endif |
179 | // -------------------------------------------------------------------------- |
180 | }; |
181 | |
182 | // ============================================================================ |
183 | // [BLImage - Core] |
184 | // ============================================================================ |
185 | |
186 | //! Image [C Interface - Impl]. |
187 | struct BLImageImpl { |
188 | //! Pixel data. |
189 | void* pixelData; |
190 | //! Image stride. |
191 | intptr_t stride; |
192 | //! Non-null if the image has a writer. |
193 | volatile void* writer; |
194 | |
195 | //! Reference count. |
196 | volatile size_t refCount; |
197 | //! Impl type. |
198 | uint8_t implType; |
199 | //! Impl traits. |
200 | uint8_t implTraits; |
201 | //! Memory pool data. |
202 | uint16_t memPoolData; |
203 | |
204 | //! Image format. |
205 | uint8_t format; |
206 | //! Image flags. |
207 | uint8_t flags; |
208 | //! Image depth (in bits). |
209 | uint16_t depth; |
210 | //! Image size. |
211 | BLSizeI size; |
212 | }; |
213 | |
214 | //! Image [C Interface - Core]. |
215 | struct BLImageCore { |
216 | BLImageImpl* impl; |
217 | }; |
218 | |
219 | // ============================================================================ |
220 | // [BLImage - C++] |
221 | // ============================================================================ |
222 | |
223 | #ifdef __cplusplus |
224 | //! 2D raster image [C++ API]. |
225 | class BLImage : public BLImageCore { |
226 | public: |
227 | //! \cond INTERNAL |
228 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_IMAGE; |
229 | //! \endcond |
230 | |
231 | //! \name Construction & Destruction |
232 | //! \{ |
233 | |
234 | BL_INLINE BLImage() noexcept { this->impl = none().impl; } |
235 | BL_INLINE BLImage(BLImage&& other) noexcept { blVariantInitMove(this, &other); } |
236 | BL_INLINE BLImage(const BLImage& other) noexcept { blVariantInitWeak(this, &other); } |
237 | BL_INLINE explicit BLImage(BLImageImpl* impl) noexcept { this->impl = impl; } |
238 | BL_INLINE BLImage(int w, int h, uint32_t format) noexcept { blImageInitAs(this, w, h, format); } |
239 | BL_INLINE ~BLImage() { blImageReset(this); } |
240 | |
241 | //! \} |
242 | |
243 | //! \name Operator Overloads |
244 | //! \{ |
245 | |
246 | BL_INLINE explicit operator bool() const noexcept { return !empty(); } |
247 | |
248 | BL_INLINE BLImage& operator=(BLImage&& other) noexcept { blImageAssignMove(this, &other); return *this; } |
249 | BL_INLINE BLImage& operator=(const BLImage& other) noexcept { blImageAssignWeak(this, &other); return *this; } |
250 | |
251 | BL_INLINE bool operator==(const BLImage& other) const noexcept { return equals(other); } |
252 | BL_INLINE bool operator!=(const BLImage& other) const noexcept { return !equals(other); } |
253 | |
254 | //! \} |
255 | |
256 | //! \name Common Functionality |
257 | //! \{ |
258 | |
259 | BL_INLINE BLResult reset() noexcept { return blImageReset(this); } |
260 | BL_INLINE void swap(BLImage& other) noexcept { std::swap(this->impl, other.impl); } |
261 | |
262 | BL_INLINE BLResult assign(BLImage&& other) noexcept { return blImageAssignMove(this, &other); } |
263 | BL_INLINE BLResult assign(const BLImage& other) noexcept { return blImageAssignWeak(this, &other); } |
264 | |
265 | //! Create a deep copy of the `other` image. |
266 | BL_INLINE BLResult assignDeep(const BLImage& other) noexcept { return blImageAssignDeep(this, &other); } |
267 | |
268 | //! Tests whether the image is a built-in null instance. |
269 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
270 | //! Tests whether the image is empty (has no size). |
271 | BL_INLINE bool empty() const noexcept { return impl->format == BL_FORMAT_NONE; } |
272 | |
273 | BL_INLINE bool equals(const BLImage& other) const noexcept { return blImageEquals(this, &other); } |
274 | |
275 | //! \} |
276 | |
277 | //! \name Create Functionality |
278 | //! \{ |
279 | |
280 | //! Create a new image of a specified width `w`, height `h`, and `format`. |
281 | //! |
282 | //! \note It's important to always test whether the function succeeded as |
283 | //! allocating pixel-data can fail. If invalid arguments (invalid size or |
284 | //! format) were passed to the function a `BL_ERROR_INVALID_VALUE` result |
285 | //! will be returned and no data will be allocated. It's also important |
286 | //! to notice that `BLImage::create()` would not change anything if the |
287 | //! function fails (the previous image content would be kept as is). |
288 | BL_INLINE BLResult create(int w, int h, uint32_t format) noexcept { |
289 | return blImageCreate(this, w, h, format); |
290 | } |
291 | |
292 | //! Create a new image from external data. |
293 | BL_INLINE BLResult createFromData( |
294 | int w, int h, uint32_t format, |
295 | void* pixelData, intptr_t stride, |
296 | BLDestroyImplFunc destroyFunc = nullptr, |
297 | void* destroyData = nullptr) noexcept { return blImageCreateFromData(this, w, h, format, pixelData, stride, destroyFunc, destroyData); } |
298 | |
299 | //! \} |
300 | |
301 | //! \name Image Data |
302 | //! \{ |
303 | |
304 | //! Returns image width. |
305 | BL_INLINE int width() const noexcept { return impl->size.w; } |
306 | //! Returns image height. |
307 | BL_INLINE int height() const noexcept { return impl->size.h; } |
308 | //! Returns image size. |
309 | BL_INLINE const BLSizeI& size() const noexcept { return impl->size; } |
310 | //! Returns image format, see `BLFormat`. |
311 | BL_INLINE uint32_t format() const noexcept { return impl->format; } |
312 | |
313 | BL_INLINE BLResult getData(BLImageData* dataOut) const noexcept { return blImageGetData(this, dataOut); } |
314 | BL_INLINE BLResult makeMutable() noexcept { BLImageData unused; return blImageMakeMutable(this, &unused); } |
315 | BL_INLINE BLResult makeMutable(BLImageData* dataOut) noexcept { return blImageMakeMutable(this, dataOut); } |
316 | |
317 | //! \} |
318 | |
319 | //! \name Image IO |
320 | //! \{ |
321 | |
322 | BL_INLINE BLResult readFromFile(const char* fileName) noexcept { |
323 | return blImageReadFromFile(this, fileName, nullptr); |
324 | } |
325 | |
326 | BL_INLINE BLResult readFromFile(const char* fileName, const BLArray<BLImageCodec>& codecs) noexcept { |
327 | return blImageReadFromFile(this, fileName, &codecs); |
328 | } |
329 | |
330 | BL_INLINE BLResult readFromData(const void* data, size_t size) noexcept { |
331 | return blImageReadFromData(this, data, size, nullptr); |
332 | } |
333 | |
334 | BL_INLINE BLResult readFromData(const void* data, size_t size, const BLArray<BLImageCodec>& codecs) noexcept { |
335 | return blImageReadFromData(this, data, size, &codecs); |
336 | } |
337 | |
338 | BL_INLINE BLResult readFromData(const BLArray<uint8_t>& array) noexcept { |
339 | return blImageReadFromData(this, array.data(), array.size(), nullptr); |
340 | } |
341 | |
342 | BL_INLINE BLResult readFromData(const BLArray<uint8_t>& array, const BLArray<BLImageCodec>& codecs) noexcept { |
343 | return blImageReadFromData(this, array.data(), array.size(), &codecs); |
344 | } |
345 | |
346 | BL_INLINE BLResult readFromData(const BLArrayView<uint8_t>& view) noexcept { |
347 | return blImageReadFromData(this, view.data, view.size, nullptr); |
348 | } |
349 | |
350 | BL_INLINE BLResult readFromData(const BLArrayView<uint8_t>& view, const BLArray<BLImageCodec>& codecs) noexcept { |
351 | return blImageReadFromData(this, view.data, view.size, &codecs); |
352 | } |
353 | |
354 | BL_INLINE BLResult writeToFile(const char* fileName, const BLImageCodec& codec) noexcept { |
355 | return blImageWriteToFile(this, fileName, reinterpret_cast<const BLImageCodecCore*>(&codec)); |
356 | } |
357 | |
358 | BL_INLINE BLResult writeToData(BLArray<uint8_t>& dst, const BLImageCodec& codec) noexcept { |
359 | return blImageWriteToData(this, &dst, reinterpret_cast<const BLImageCodecCore*>(&codec)); |
360 | } |
361 | |
362 | //! \} |
363 | |
364 | static BL_INLINE const BLImage& none() noexcept { return reinterpret_cast<const BLImage*>(blNone)[kImplType]; } |
365 | |
366 | static BL_INLINE BLResult scale(BLImage& dst, const BLImage& src, const BLSizeI& size, uint32_t filter, const BLImageScaleOptions* options = nullptr) noexcept { |
367 | return blImageScale(&dst, &src, &size, filter, options); |
368 | } |
369 | }; |
370 | #endif |
371 | |
372 | // ============================================================================ |
373 | // [BLImageCodec - Core] |
374 | // ============================================================================ |
375 | |
376 | //! Image codec [C Interface - Virtual Function Table]. |
377 | struct BLImageCodecVirt { |
378 | BLResult (BL_CDECL* destroy)(BLImageCodecImpl* impl) BL_NOEXCEPT; |
379 | uint32_t (BL_CDECL* inspectData)(const BLImageCodecImpl* impl, const uint8_t* data, size_t size) BL_NOEXCEPT; |
380 | BLResult (BL_CDECL* createDecoder)(const BLImageCodecImpl* impl, BLImageDecoderCore* dst) BL_NOEXCEPT; |
381 | BLResult (BL_CDECL* createEncoder)(const BLImageCodecImpl* impl, BLImageEncoderCore* dst) BL_NOEXCEPT; |
382 | }; |
383 | |
384 | //! Image codec [C Interface - Impl]. |
385 | struct BLImageCodecImpl { |
386 | //! Virtual function table. |
387 | const BLImageCodecVirt* virt; |
388 | //! Image codec name like "PNG", "JPEG", etc... |
389 | const char* name; |
390 | //! Image codec vendor, built-in codecs use "Blend2D". |
391 | const char* vendor; |
392 | |
393 | //! Reference count. |
394 | volatile size_t refCount; |
395 | //! Impl type. |
396 | uint8_t implType; |
397 | //! Impl traits. |
398 | uint8_t implTraits; |
399 | //! Memory pool data. |
400 | uint16_t memPoolData; |
401 | |
402 | //! Image codec features. |
403 | uint32_t features; |
404 | //! Mime type. |
405 | const char* mimeType; |
406 | //! Known file extensions used by this image codec separated by "|". |
407 | const char* extensions; |
408 | }; |
409 | |
410 | //! Image codec [C Interface - Core]. |
411 | struct BLImageCodecCore { |
412 | BLImageCodecImpl* impl; |
413 | }; |
414 | |
415 | // ============================================================================ |
416 | // [BLImageCodec - C++] |
417 | // ============================================================================ |
418 | |
419 | #ifdef __cplusplus |
420 | //! Image codec [C++ API]. |
421 | //! |
422 | //! Provides a unified interface for inspecting image data and creating image |
423 | //! decoders & encoders. |
424 | class BLImageCodec : public BLImageCodecCore { |
425 | public: |
426 | //! \cond INTERNAL |
427 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_IMAGE_CODEC; |
428 | //! \endcond |
429 | |
430 | //! \name Construction & Destruction |
431 | //! \{ |
432 | |
433 | BL_INLINE BLImageCodec() noexcept { this->impl = none().impl; } |
434 | BL_INLINE BLImageCodec(BLImageCodec&& other) noexcept { blVariantInitMove(this, &other); } |
435 | BL_INLINE BLImageCodec(const BLImageCodec& other) noexcept { blVariantInitWeak(this, &other); } |
436 | BL_INLINE explicit BLImageCodec(BLImageCodecImpl* impl) noexcept { this->impl = impl; } |
437 | BL_INLINE ~BLImageCodec() { blImageCodecReset(this); } |
438 | |
439 | //! \} |
440 | |
441 | //! \name Operator Overloads |
442 | //! \{ |
443 | |
444 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
445 | |
446 | BL_INLINE BLImageCodec& operator=(const BLImageCodec& other) noexcept { |
447 | blImageCodecAssignWeak(this, &other); |
448 | return *this; |
449 | } |
450 | |
451 | BL_INLINE bool operator==(const BLImageCodec& other) const noexcept { return equals(other); } |
452 | BL_INLINE bool operator!=(const BLImageCodec& other) const noexcept { return !equals(other); } |
453 | |
454 | //! \} |
455 | |
456 | //! \name Common Functionality |
457 | //! \{ |
458 | |
459 | BL_INLINE BLResult reset() noexcept { return blImageCodecReset(this); } |
460 | BL_INLINE void swap(BLImageCodec& other) noexcept { std::swap(this->impl, other.impl); } |
461 | |
462 | BL_INLINE BLResult assign(const BLImageCodec& other) noexcept { return blImageCodecAssignWeak(this, &other); } |
463 | |
464 | //! Tests whether the image codec is a built-in null instance. |
465 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
466 | |
467 | BL_INLINE bool equals(const BLImageCodec& other) const noexcept { return this->impl == other.impl; } |
468 | |
469 | //! \} |
470 | |
471 | //! \name Properties |
472 | //! \{ |
473 | |
474 | //! Returns image codec name (i.e, "PNG", "JPEG", etc...). |
475 | BL_INLINE const char* name() const noexcept { return impl->name; } |
476 | //! Returns the image codec vendor (i.e. "Blend2D" for all built-in codecs). |
477 | BL_INLINE const char* vendor() const noexcept { return impl->vendor; } |
478 | //! Returns a mime-type associated with the image codec's format. |
479 | BL_INLINE const char* mimeType() const noexcept { return impl->mimeType; } |
480 | //! Returns a list of file extensions used to store image of this codec, separated by '|' character. |
481 | BL_INLINE const char* extensions() const noexcept { return impl->extensions; } |
482 | //! Returns image codec flags, see `BLImageCodecFeatures`. |
483 | BL_INLINE uint32_t features() const noexcept { return impl->features; } |
484 | //! Tests whether the image codec has a flag `flag`. |
485 | BL_INLINE bool hasFeature(uint32_t feature) const noexcept { return (impl->features & feature) != 0; } |
486 | |
487 | //! \} |
488 | |
489 | //! \name Find Functionality |
490 | //! \{ |
491 | |
492 | BL_INLINE BLResult findByName(const char* name) noexcept { |
493 | return blImageCodecFindByName(this, name, SIZE_MAX, nullptr); |
494 | } |
495 | |
496 | BL_INLINE BLResult findByName(const char* name, const BLArray<BLImageCodec>& codecs) noexcept { |
497 | return blImageCodecFindByName(this, name, SIZE_MAX, &codecs); |
498 | } |
499 | |
500 | BL_INLINE BLResult findByName(const BLStringView& name) noexcept { |
501 | return blImageCodecFindByName(this, name.data, name.size, nullptr); |
502 | } |
503 | |
504 | BL_INLINE BLResult findByName(const BLStringView& name, const BLArray<BLImageCodec>& codecs) noexcept { |
505 | return blImageCodecFindByName(this, name.data, name.size, &codecs); |
506 | } |
507 | |
508 | BL_INLINE BLResult findByData(const void* data, size_t size) noexcept { |
509 | return blImageCodecFindByData(this, data, size, nullptr); |
510 | } |
511 | |
512 | BL_INLINE BLResult findByData(const void* data, size_t size, const BLArray<BLImageCodec>& codecs) noexcept { |
513 | return blImageCodecFindByData(this, data, size, &codecs); |
514 | } |
515 | |
516 | BL_INLINE BLResult findByData(const BLArrayView<uint8_t>& view) noexcept { |
517 | return blImageCodecFindByData(this, view.data, view.size, nullptr); |
518 | } |
519 | |
520 | BL_INLINE BLResult findByData(const BLArrayView<uint8_t>& view, const BLArray<BLImageCodec>& codecs) noexcept { |
521 | return blImageCodecFindByData(this, view.data, view.size, &codecs); |
522 | } |
523 | |
524 | BL_INLINE BLResult findByData(const BLArray<uint8_t>& buffer) noexcept { |
525 | return blImageCodecFindByData(this, buffer.data(), buffer.size(), nullptr); |
526 | } |
527 | |
528 | BL_INLINE BLResult findByData(const BLArray<uint8_t>& buffer, const BLArray<BLImageCodec>& codecs) noexcept { |
529 | return blImageCodecFindByData(this, buffer.data(), buffer.size(), &codecs); |
530 | } |
531 | |
532 | //! \} |
533 | |
534 | //! \name Codec Functionality |
535 | //! \{ |
536 | |
537 | BL_INLINE uint32_t inspectData(const BLArray<uint8_t>& buffer) const noexcept { return inspectData(buffer.view()); } |
538 | BL_INLINE uint32_t inspectData(const BLArrayView<uint8_t>& view) const noexcept { return inspectData(view.data, view.size); } |
539 | BL_INLINE uint32_t inspectData(const void* data, size_t size) const noexcept { return blImageCodecInspectData(this, static_cast<const uint8_t*>(data), size); } |
540 | |
541 | BL_INLINE BLResult createDecoder(BLImageDecoder* dst) const noexcept { return blImageCodecCreateDecoder(this, reinterpret_cast<BLImageDecoderCore*>(dst)); } |
542 | BL_INLINE BLResult createEncoder(BLImageEncoder* dst) const noexcept { return blImageCodecCreateEncoder(this, reinterpret_cast<BLImageEncoderCore*>(dst)); } |
543 | |
544 | //! \} |
545 | |
546 | //! \name Built-In Codecs |
547 | //! \{ |
548 | |
549 | static BL_INLINE BLArray<BLImageCodec> builtInCodecs() noexcept { |
550 | BLArray<BLImageCodec> result(nullptr); |
551 | blImageCodecArrayInitBuiltInCodecs(&result); |
552 | return result; |
553 | } |
554 | |
555 | static BL_INLINE BLResult addToBuiltIn(const BLImageCodec& codec) noexcept { |
556 | return blImageCodecAddToBuiltIn(&codec); |
557 | } |
558 | |
559 | static BL_INLINE BLResult removeFromBuiltIn(const BLImageCodec& codec) noexcept { |
560 | return blImageCodecRemoveFromBuiltIn(&codec); |
561 | } |
562 | |
563 | //! \} |
564 | |
565 | static BL_INLINE const BLImageCodec& none() noexcept { return reinterpret_cast<const BLImageCodec*>(blNone)[kImplType]; } |
566 | }; |
567 | #endif |
568 | |
569 | // ============================================================================ |
570 | // [BLImageDecoder - Core] |
571 | // ============================================================================ |
572 | |
573 | //! Image decoder [C Interface - Virtual Function Table]. |
574 | struct BLImageDecoderVirt { |
575 | BLResult (BL_CDECL* destroy)(BLImageDecoderImpl* impl) BL_NOEXCEPT; |
576 | BLResult (BL_CDECL* restart)(BLImageDecoderImpl* impl) BL_NOEXCEPT; |
577 | BLResult (BL_CDECL* readInfo)(BLImageDecoderImpl* impl, BLImageInfo* infoOut, const uint8_t* data, size_t size) BL_NOEXCEPT; |
578 | BLResult (BL_CDECL* readFrame)(BLImageDecoderImpl* impl, BLImageCore* imageOut, const uint8_t* data, size_t size) BL_NOEXCEPT; |
579 | }; |
580 | |
581 | //! Image decoder [C Interface - Impl]. |
582 | struct BLImageDecoderImpl { |
583 | //! Virtual function table. |
584 | const BLImageDecoderVirt* virt; |
585 | //! Image codec that created this decoder. |
586 | BL_TYPED_MEMBER(BLImageCodecCore, BLImageCodec, codec); |
587 | //! Handle in case that this decoder wraps a thirt-party library. |
588 | void* handle; |
589 | |
590 | //! Reference count. |
591 | volatile size_t refCount; |
592 | //! Impl type. |
593 | uint8_t implType; |
594 | //! Impl traits. |
595 | uint8_t implTraits; |
596 | //! Memory pool data. |
597 | uint16_t memPoolData; |
598 | |
599 | //! Last faulty result (if failed). |
600 | BLResult lastResult; |
601 | //! Current frame index. |
602 | uint64_t frameIndex; |
603 | //! Position in source buffer. |
604 | size_t bufferIndex; |
605 | |
606 | BL_HAS_TYPED_MEMBERS(BLImageDecoderImpl) |
607 | }; |
608 | |
609 | //! Image decoder [C Interface - Core] |
610 | struct BLImageDecoderCore { |
611 | BLImageDecoderImpl* impl; |
612 | }; |
613 | |
614 | // ============================================================================ |
615 | // [BLImageDecoder - C++] |
616 | // ============================================================================ |
617 | |
618 | #ifdef __cplusplus |
619 | //! Image decoder [C++ API]. |
620 | class BLImageDecoder : public BLImageDecoderCore { |
621 | public: |
622 | //! \cond INTERNAL |
623 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_IMAGE_DECODER; |
624 | //! \endcond |
625 | |
626 | //! \name Construction & Destruction |
627 | //! \{ |
628 | |
629 | BL_INLINE BLImageDecoder() noexcept { this->impl = none().impl; } |
630 | BL_INLINE BLImageDecoder(BLImageDecoder&& other) noexcept { blVariantInitMove(this, &other); } |
631 | BL_INLINE BLImageDecoder(const BLImageDecoder& other) noexcept { blVariantInitWeak(this, &other); } |
632 | BL_INLINE explicit BLImageDecoder(BLImageDecoderImpl* impl) noexcept { this->impl = impl; } |
633 | BL_INLINE ~BLImageDecoder() { blImageDecoderReset(this); } |
634 | |
635 | //! \} |
636 | |
637 | //! \name Operator Overloads |
638 | //! \{ |
639 | |
640 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
641 | |
642 | BL_INLINE BLImageDecoder& operator=(BLImageDecoder&& other) noexcept { blImageDecoderAssignMove(this, &other); return *this; } |
643 | BL_INLINE BLImageDecoder& operator=(const BLImageDecoder& other) noexcept { blImageDecoderAssignWeak(this, &other); return *this; } |
644 | |
645 | BL_INLINE bool operator==(const BLImageDecoder& other) const noexcept { return equals(other); } |
646 | BL_INLINE bool operator!=(const BLImageDecoder& other) const noexcept { return !equals(other); } |
647 | |
648 | //! \} |
649 | |
650 | //! \name Common Functionality |
651 | //! \{ |
652 | |
653 | BL_INLINE BLResult reset() noexcept { return blImageDecoderReset(this); } |
654 | BL_INLINE void swap(BLImageDecoder& other) noexcept { std::swap(this->impl, other.impl); } |
655 | |
656 | BL_INLINE BLResult assign(BLImageDecoder&& other) noexcept { return blImageDecoderAssignMove(this, &other); } |
657 | BL_INLINE BLResult assign(const BLImageDecoder& other) noexcept { return blImageDecoderAssignWeak(this, &other); } |
658 | |
659 | //! Tests whether the image decoder is a built-in null instance. |
660 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
661 | |
662 | BL_INLINE bool equals(const BLImageDecoder& other) const noexcept { return this->impl == other.impl; } |
663 | |
664 | //! \} |
665 | |
666 | //! \name Properties |
667 | //! \{ |
668 | |
669 | //! Returns the last decoding result. |
670 | BL_INLINE BLResult lastResult() const noexcept { return impl->lastResult; } |
671 | //! Returns the current frame index (to be decoded). |
672 | BL_INLINE uint64_t frameIndex() const noexcept { return impl->frameIndex; } |
673 | //! Returns the position in source buffer. |
674 | BL_INLINE size_t bufferIndex() const noexcept { return impl->bufferIndex; } |
675 | |
676 | //! \} |
677 | |
678 | //! \name Decoder Functionality |
679 | //! \{ |
680 | |
681 | BL_INLINE BLResult restart() noexcept { return blImageDecoderRestart(this); } |
682 | |
683 | BL_INLINE BLResult readInfo(BLImageInfo& dst, const BLArray<uint8_t>& buffer) noexcept { return blImageDecoderReadInfo(this, &dst, buffer.data(), buffer.size()); } |
684 | BL_INLINE BLResult readInfo(BLImageInfo& dst, const BLArrayView<uint8_t>& view) noexcept { return blImageDecoderReadInfo(this, &dst, view.data, view.size); } |
685 | BL_INLINE BLResult readInfo(BLImageInfo& dst, const void* data, size_t size) noexcept { return blImageDecoderReadInfo(this, &dst, static_cast<const uint8_t*>(data), size); } |
686 | |
687 | BL_INLINE BLResult readFrame(BLImage& dst, const BLArray<uint8_t>& buffer) noexcept { return blImageDecoderReadFrame(this, &dst, buffer.data(), buffer.size()); } |
688 | BL_INLINE BLResult readFrame(BLImage& dst, const BLArrayView<uint8_t>& view) noexcept { return blImageDecoderReadFrame(this, &dst, view.data, view.size); } |
689 | BL_INLINE BLResult readFrame(BLImage& dst, const void* data, size_t size) noexcept { return blImageDecoderReadFrame(this, &dst, static_cast<const uint8_t*>(data), size); } |
690 | |
691 | //! \} |
692 | |
693 | static BL_INLINE const BLImageDecoder& none() noexcept { return reinterpret_cast<const BLImageDecoder*>(blNone)[kImplType]; } |
694 | }; |
695 | #endif |
696 | |
697 | // ============================================================================ |
698 | // [BLImageEncoder - Core] |
699 | // ============================================================================ |
700 | |
701 | //! Image encoder [C Interface - Virtual Function Table]. |
702 | struct BLImageEncoderVirt { |
703 | BLResult (BL_CDECL* destroy)(BLImageEncoderImpl* impl) BL_NOEXCEPT; |
704 | BLResult (BL_CDECL* restart)(BLImageEncoderImpl* impl) BL_NOEXCEPT; |
705 | BLResult (BL_CDECL* writeFrame)(BLImageEncoderImpl* impl, BLArrayCore* dst, const BLImageCore* image) BL_NOEXCEPT; |
706 | }; |
707 | |
708 | //! Image encoder [C Interface - Impl]. |
709 | struct BLImageEncoderImpl { |
710 | //! Virtual function table. |
711 | const BLImageEncoderVirt* virt; |
712 | //! Image codec that created this encoder. |
713 | BL_TYPED_MEMBER(BLImageCodecCore, BLImageCodec, codec); |
714 | //! Handle in case that this encoder wraps a thirt-party library. |
715 | void* handle; |
716 | |
717 | //! Reference count. |
718 | volatile size_t refCount; |
719 | //! Impl type. |
720 | uint8_t implType; |
721 | //! Impl traits. |
722 | uint8_t implTraits; |
723 | //! Memory pool data. |
724 | uint16_t memPoolData; |
725 | |
726 | //! Last faulty result (if failed). |
727 | BLResult lastResult; |
728 | //! Current frame index. |
729 | uint64_t frameIndex; |
730 | //! Position in source buffer. |
731 | size_t bufferIndex; |
732 | |
733 | BL_HAS_TYPED_MEMBERS(BLImageEncoderImpl) |
734 | }; |
735 | |
736 | //! Image encoder [C Interface - Core]. |
737 | struct BLImageEncoderCore { |
738 | BLImageEncoderImpl* impl; |
739 | }; |
740 | |
741 | // ============================================================================ |
742 | // [BLImageEncoder - C++] |
743 | // ============================================================================ |
744 | |
745 | #ifdef __cplusplus |
746 | //! Image encoder [C++ API]. |
747 | class BLImageEncoder : public BLImageEncoderCore { |
748 | public: |
749 | //! \cond INTERNAL |
750 | static constexpr const uint32_t kImplType = BL_IMPL_TYPE_IMAGE_ENCODER; |
751 | //! \endcond |
752 | |
753 | //! \name Construction & Destruction |
754 | //! \{ |
755 | |
756 | BL_INLINE BLImageEncoder() noexcept { this->impl = none().impl; } |
757 | BL_INLINE BLImageEncoder(BLImageEncoder&& other) noexcept { blVariantInitMove(this, &other); } |
758 | BL_INLINE BLImageEncoder(const BLImageEncoder& other) noexcept { blVariantInitWeak(this, &other); } |
759 | BL_INLINE explicit BLImageEncoder(BLImageEncoderImpl* impl) noexcept { this->impl = impl; } |
760 | BL_INLINE ~BLImageEncoder() { blImageEncoderReset(this); } |
761 | |
762 | //! \} |
763 | |
764 | //! \name Operator Overloads |
765 | //! \{ |
766 | |
767 | BL_INLINE explicit operator bool() const noexcept { return !isNone(); } |
768 | |
769 | BL_INLINE BLImageEncoder& operator=(BLImageEncoder&& other) noexcept { blImageEncoderAssignMove(this, &other); return *this; } |
770 | BL_INLINE BLImageEncoder& operator=(const BLImageEncoder& other) noexcept { blImageEncoderAssignWeak(this, &other); return *this; } |
771 | |
772 | BL_INLINE bool operator==(const BLImageEncoder& other) const noexcept { return equals(other); } |
773 | BL_INLINE bool operator!=(const BLImageEncoder& other) const noexcept { return !equals(other); } |
774 | |
775 | //! \} |
776 | |
777 | //! \name Common Functionality |
778 | //! \{ |
779 | |
780 | BL_INLINE BLResult reset() noexcept { return blImageEncoderReset(this); } |
781 | BL_INLINE void swap(BLImageEncoder& other) noexcept { std::swap(this->impl, other.impl); } |
782 | |
783 | BL_INLINE BLResult assign(BLImageEncoder&& other) noexcept { return blImageEncoderAssignMove(this, &other); } |
784 | BL_INLINE BLResult assign(const BLImageEncoder& other) noexcept { return blImageEncoderAssignWeak(this, &other); } |
785 | |
786 | //! Tests whether the image encoder is a built-in null instance. |
787 | BL_INLINE bool isNone() const noexcept { return (impl->implTraits & BL_IMPL_TRAIT_NULL) != 0; } |
788 | |
789 | BL_INLINE bool equals(const BLImageEncoder& other) const noexcept { return this->impl == other.impl; } |
790 | |
791 | //! \} |
792 | |
793 | //! \name Properties |
794 | //! \{ |
795 | |
796 | //! Returns the last decoding result. |
797 | BL_INLINE BLResult lastResult() const noexcept { return impl->lastResult; } |
798 | //! Returns the current frame index (yet to be written). |
799 | BL_INLINE uint64_t frameIndex() const noexcept { return impl->frameIndex; } |
800 | //! Returns the position in destination buffer. |
801 | BL_INLINE size_t bufferIndex() const noexcept { return impl->bufferIndex; } |
802 | |
803 | //! \} |
804 | |
805 | //! \name Encoder Functionality |
806 | //! \{ |
807 | |
808 | BL_INLINE BLResult restart() noexcept { return blImageEncoderRestart(this); } |
809 | |
810 | //! Encodes the given `image` and writes the encoded data to the destination buffer `dst`. |
811 | BL_INLINE BLResult writeFrame(BLArray<uint8_t>& dst, const BLImage& image) noexcept { return blImageEncoderWriteFrame(this, &dst, &image); } |
812 | |
813 | //! \} |
814 | |
815 | static BL_INLINE const BLImageEncoder& none() noexcept { return reinterpret_cast<const BLImageEncoder*>(blNone)[kImplType]; } |
816 | }; |
817 | #endif |
818 | |
819 | //! \} |
820 | |
821 | #endif // BLEND2D_BLIMAGE_H |
822 | |