17#define VTFPP_FORMAT_ACCESSOR(channel, channelCaps) \
18 [[nodiscard]] constexpr auto channel() const { \
19 if constexpr (std::endian::native == std::endian::little) { \
20 return pixel.le.channel; \
22 return pixel.be.channel; \
25 constexpr void set##channelCaps(decltype(pixel.le.channel) value) { \
26 if constexpr (std::endian::native == std::endian::little) { \
27 pixel.le.channel = value; \
29 pixel.be.channel = value; \
33#define VTFPP_A VTFPP_FORMAT_ACCESSOR(a, A)
34#define VTFPP_B VTFPP_FORMAT_ACCESSOR(b, B)
35#define VTFPP_G VTFPP_FORMAT_ACCESSOR(g, G)
36#define VTFPP_I VTFPP_FORMAT_ACCESSOR(i, I)
37#define VTFPP_L VTFPP_FORMAT_ACCESSOR(l, L)
38#define VTFPP_P VTFPP_FORMAT_ACCESSOR(p, P)
39#define VTFPP_Q VTFPP_FORMAT_ACCESSOR(q, Q)
40#define VTFPP_R VTFPP_FORMAT_ACCESSOR(r, R)
41#define VTFPP_U VTFPP_FORMAT_ACCESSOR(u, U)
42#define VTFPP_V VTFPP_FORMAT_ACCESSOR(v, V)
43#define VTFPP_W VTFPP_FORMAT_ACCESSOR(w, W)
44#define VTFPP_X VTFPP_FORMAT_ACCESSOR(x, X)
46#define VTFPP_FORMAT_ACCESSOR_BSWAP(format, channel, channelCaps) \
47 [[nodiscard]] constexpr auto channel() const { \
48 if constexpr (std::endian::native == std::endian::little) { \
49 return pixel.le.channel; \
51 auto swapped = pixel.be.data; \
52 BufferStream::swap_endian(&swapped); \
53 return std::bit_cast<LE>(swapped).channel; \
56 constexpr void set##channelCaps(decltype(pixel.le.channel) value) { \
57 if constexpr (std::endian::native == std::endian::little) { \
58 pixel.le.channel = value; \
60 auto pixelLE = std::bit_cast<LE>(pixel.be.data); \
61 pixelLE.channel = value; \
62 auto swapped = std::bit_cast<decltype(pixel.be.data)>(pixelLE); \
63 BufferStream::swap_endian(&swapped); \
64 pixel.be.data = swapped; \
68#define VTFPP_A_BSWAP(format) VTFPP_FORMAT_ACCESSOR_BSWAP(format, a, A)
69#define VTFPP_B_BSWAP(format) VTFPP_FORMAT_ACCESSOR_BSWAP(format, b, B)
70#define VTFPP_G_BSWAP(format) VTFPP_FORMAT_ACCESSOR_BSWAP(format, g, G)
71#define VTFPP_R_BSWAP(format) VTFPP_FORMAT_ACCESSOR_BSWAP(format, r, R)
72#define VTFPP_X_BSWAP(format) VTFPP_FORMAT_ACCESSOR_BSWAP(format, x, X)
74#define VTFPP_FORMAT_INTERNAL(bo, ...) \
77 }; static_assert(std::is_trivially_copyable_v<bo> && sizeof(bo) == ImageFormatDetails::bpp(FORMAT) / 8);
79#define VTFPP_FORMAT_LE(...) VTFPP_FORMAT_INTERNAL(LE, __VA_ARGS__)
80#define VTFPP_FORMAT_BE(...) VTFPP_FORMAT_INTERNAL(BE, __VA_ARGS__)
82#define VTFPP_FORMAT(format, internalFormatClasses, accessors) \
85 static constexpr auto FORMAT = ImageFormat::format; \
86 internalFormatClasses \
91 Pixel() { std::memset(this, 0, sizeof(Pixel)); } \
96 if constexpr (std::endian::native == std::endian::little) { \
97 this->pixel.le = le; \
99 BufferStream::swap_endian(&le); \
100 this->pixel.be = std::bit_cast<BE>(le); \
104}; static_assert(std::is_trivially_copyable_v<format> && sizeof(format) == ImageFormatDetails::bpp(ImageFormat::format) / 8)
443#undef VTFPP_FORMAT_BE
444#undef VTFPP_FORMAT_LE
445#undef VTFPP_FORMAT_INTERNAL
451#undef VTFPP_FORMAT_ACCESSOR_BSWAP
464#undef VTFPP_FORMAT_ACCESSOR
468 std::same_as<T, RGBA8888> ||
469 std::same_as<T, ABGR8888> ||
470 std::same_as<T, RGB888> ||
471 std::same_as<T, BGR888> ||
472 std::same_as<T, RGB565> ||
473 std::same_as<T, I8> ||
474 std::same_as<T, IA88> ||
475 std::same_as<T, P8> ||
476 std::same_as<T, A8> ||
477 std::same_as<T, RGB888_BLUESCREEN> ||
478 std::same_as<T, BGR888_BLUESCREEN> ||
479 std::same_as<T, ARGB8888> ||
480 std::same_as<T, BGRA8888> ||
481 std::same_as<T, BGRX8888> ||
482 std::same_as<T, BGR565> ||
483 std::same_as<T, BGRX5551> ||
484 std::same_as<T, BGRA4444> ||
485 std::same_as<T, BGRA5551> ||
486 std::same_as<T, UV88> ||
487 std::same_as<T, UVWQ8888> ||
488 std::same_as<T, RGBA16161616F> ||
489 std::same_as<T, RGBA16161616> ||
490 std::same_as<T, UVLX8888> ||
491 std::same_as<T, R32F> ||
492 std::same_as<T, RGB323232F> ||
493 std::same_as<T, RGBA32323232F> ||
494 std::same_as<T, RG1616F> ||
495 std::same_as<T, RG3232F> ||
496 std::same_as<T, RGBX8888> ||
497 std::same_as<T, RGBA1010102> ||
498 std::same_as<T, BGRA1010102> ||
499 std::same_as<T, R16F> ||
500 std::same_as<T, CONSOLE_BGRX8888_LINEAR> ||
501 std::same_as<T, CONSOLE_RGBA8888_LINEAR> ||
502 std::same_as<T, CONSOLE_ABGR8888_LINEAR> ||
503 std::same_as<T, CONSOLE_ARGB8888_LINEAR> ||
504 std::same_as<T, CONSOLE_BGRA8888_LINEAR> ||
505 std::same_as<T, CONSOLE_RGB888_LINEAR> ||
506 std::same_as<T, CONSOLE_BGR888_LINEAR> ||
507 std::same_as<T, CONSOLE_BGRX5551_LINEAR> ||
508 std::same_as<T, CONSOLE_I8_LINEAR> ||
509 std::same_as<T, CONSOLE_RGBA16161616_LINEAR> ||
510 std::same_as<T, CONSOLE_BGRX8888_LE> ||
511 std::same_as<T, CONSOLE_BGRA8888_LE> ||
512 std::same_as<T, STRATA_R8> ||
513 std::same_as<T, SOURCEPP_BGRA8888_HDR> ||
514 std::same_as<T, SOURCEPP_RGBA16161616_HDR> ||
515 std::same_as<T, SOURCEPP_CONSOLE_RGBA16161616_HDR>;
521template<PixelType P,
typename C>
523 if (imageData.empty() || imageData.size() %
sizeof(P) != 0 || !channel) {
527 std::vector<std::byte> out(imageData.size() /
sizeof(P) *
sizeof(C));
528 std::span outSpan{
reinterpret_cast<C*
>(out.data()), out.size() /
sizeof(C)};
530 std::span pixels{
reinterpret_cast<const P*
>(imageData.data()), imageData.size() /
sizeof(P)};
532#ifdef SOURCEPP_BUILD_WITH_TBB
533 std::execution::par_unseq,
539 return (pixel.*channel)();
547template<PixelType InputPixel,
typename Func>
549 if (imageData.empty()) {
553 std::span<InputPixel> imageDataSpan{
reinterpret_cast<InputPixel*
>(imageData.data()), imageData.size() /
sizeof(InputPixel)};
555#ifdef SOURCEPP_BUILD_WITH_TBB
556 std::execution::par_unseq,
558 imageDataSpan.begin(),
560 imageDataSpan.begin(),
566template<PixelType InputPixel, PixelType OutputPixel,
typename Func>
567[[nodiscard]] std::vector<std::byte>
transform(std::span<const std::byte> imageData, Func callback) {
568 if (imageData.empty()) {
572 std::vector<std::byte> newData;
573 newData.resize(imageData.size() /
sizeof(InputPixel) *
sizeof(OutputPixel));
574 std::span newDataSpan{
reinterpret_cast<OutputPixel*
>(newData.data()), newData.size() /
sizeof(OutputPixel)};
576 std::span<const InputPixel> imageDataSpan{
reinterpret_cast<const InputPixel*
>(imageData.data()), imageData.size() /
sizeof(InputPixel)};
578#ifdef SOURCEPP_BUILD_WITH_TBB
579 std::execution::par_unseq,
581 imageDataSpan.begin(),