pixels.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #ifndef SIMPLE_GRAPHICAL_PIXELS_H
  2. #define SIMPLE_GRAPHICAL_PIXELS_H
  3. #include <variant>
  4. #include <cassert>
  5. #include "common_def.h"
  6. #include "color_vector.hpp"
  7. namespace simple::graphical
  8. {
  9. class color;
  10. template<typename RawType>
  11. class pixels
  12. {
  13. // TODO: SDL independent pixels owner, compatible with the views below
  14. };
  15. namespace pixel_view_details
  16. {
  17. template <typename Pixel>
  18. struct pixel_fraction { using type = rgba_vector; };
  19. template <>
  20. struct pixel_fraction<rgba_pixel> { using type = rgba_vector; };
  21. template <>
  22. struct pixel_fraction<rgb_pixel> { using type = rgb_vector; };
  23. template <>
  24. struct pixel_fraction<uint16_t> { using type = float; };
  25. template <>
  26. struct pixel_fraction<pixel_byte> { using type = float; };
  27. template <typename Pixel>
  28. using pixel_fraction_t = typename pixel_fraction<Pixel>::type;
  29. class tag
  30. {
  31. public:
  32. class pixel_view {};
  33. class reader : public pixel_view {};
  34. class writer : public pixel_view {};
  35. template <typename Tag>
  36. static constexpr bool valid = std::is_base_of_v<pixel_view, Tag>;
  37. template<typename T, typename RT>
  38. using select_raw_type = std::conditional_t<std::is_same_v<T, tag::reader>, std::add_const_t<RT>, RT>;
  39. };
  40. template <typename Tag, typename Pixel, typename RawType>
  41. static constexpr bool valid_impl = tag::valid<Tag> && (sizeof(Pixel) % sizeof(RawType) == 0);
  42. // template<typename Tag, typename Pixel, typename RawType,
  43. // std::enable_if_t<valid_impl<Tag, Pixel, RawType>>* = nullptr>
  44. template<typename Tag, typename Pixel, typename RawType>
  45. class impl
  46. {
  47. protected:
  48. constexpr static int2 ratio{(int)(sizeof(Pixel) / sizeof(RawType)),1};
  49. public:
  50. using raw_type = tag::select_raw_type<Tag, RawType>;
  51. using byte_type = tag::select_raw_type<Tag, pixel_byte>;
  52. using pixel_type = Pixel;
  53. const int2& raw_size() const noexcept;
  54. int2 size() const noexcept;
  55. // TODO: proper row_iterator interface?
  56. // TODO: simple::geom::iterator/vectirator interface
  57. raw_type* row(int index = 0) const noexcept;
  58. raw_type* row_offset(raw_type* row, int offset = 1) const noexcept;
  59. raw_type* next_row(raw_type* row) const noexcept;
  60. raw_type* prev_row(raw_type* row) const noexcept;
  61. raw_type& operator[](int2 position) const noexcept;
  62. simple::support::range<raw_type*> raw_range() const noexcept;
  63. auto get(int2 position) const
  64. -> std::conditional_t<std::is_same_v<Pixel,RawType>, const Pixel&, Pixel>;
  65. template <typename ColorVector = pixel_fraction_t<Pixel>>
  66. Pixel get(float2 position) const;
  67. template <typename ColorVector = pixel_fraction_t<Pixel>>
  68. Pixel get(float2 position, range2D spread) const;
  69. impl(const impl & other, range2D range);
  70. int pitch() const noexcept;
  71. protected:
  72. impl(tag::select_raw_type<Tag,pixel_byte>* target, int2 size, int pitch = 0);
  73. template<typename OtherTag>
  74. impl(const impl<OtherTag, Pixel, RawType> & other);
  75. template<typename OtherTag>
  76. impl(const impl<OtherTag, Pixel, RawType> & other, range2D range);
  77. private:
  78. tag::select_raw_type<Tag,pixel_byte>* _raw;
  79. int2 _raw_size;
  80. int _pitch;
  81. static int to_index(const int2& position, int pitch) noexcept;
  82. };
  83. } // namespace pixel_view_details
  84. // TODO: add more pixel types, for all the crazy pixel formats SDL supports
  85. template<template<typename Pixel, typename Raw = Pixel> typename PixelView>
  86. using pixel_view_variant = std::variant<
  87. PixelView<pixel_byte>, // 1 bytes per pixel
  88. PixelView<uint16_t, pixel_byte>, // 2 bytes per pixel
  89. PixelView<rgb_pixel, pixel_byte>, // 3 bytes per pixel
  90. PixelView<rgba_pixel, pixel_byte> // 4 bytes per pixel
  91. >;
  92. static_assert(sizeof(rgb_pixel) == sizeof(rgb_pixel::value_type) * rgb_pixel::dimensions);
  93. static_assert(sizeof(rgba_pixel) == sizeof(rgba_pixel::value_type) * rgba_pixel::dimensions);
  94. static_assert(sizeof(uint16_t) == sizeof(pixel_byte) * 2);
  95. template<typename Pixel, typename RawType = Pixel>
  96. class pixel_writer :
  97. public pixel_view_details::impl<pixel_view_details::tag::writer, Pixel, RawType>
  98. {
  99. public:
  100. using impl = pixel_view_details::impl<pixel_view_details::tag::writer, Pixel, RawType>;
  101. using impl::impl;
  102. void set(const Pixel& pixel, int2 position) const;
  103. // TODO: type constraints for ColorVector
  104. template <typename ColorVector = rgba_vector>
  105. void set(const Pixel& pixel, float2 position) const;
  106. template <typename ColorVector = rgba_vector>
  107. void set(const ColorVector& pixel, float2 position) const;
  108. template <typename ColorVector = rgba_vector>
  109. void set(const Pixel& pixel, float2 position, range2D spread) const;
  110. template <typename ColorVector = rgba_vector>
  111. void set(const ColorVector& pixel, float2 position, range2D spread) const;
  112. void set(const color& pixel, int2 position) const;
  113. private:
  114. pixel_writer(pixel_byte* target, int2 size, int pitch = 0);
  115. friend pixel_view_variant<pixel_writer> pixel_writer_from_format(pixel_byte*, int2, int, int bpp);
  116. };
  117. template<typename Pixel, typename RawType>
  118. pixel_writer(pixel_writer<Pixel, RawType>, range2D)
  119. -> pixel_writer<Pixel, RawType>;
  120. template<typename Pixel, typename RawType = Pixel>
  121. class pixel_reader :
  122. public pixel_view_details::impl<pixel_view_details::tag::reader, Pixel, RawType>
  123. {
  124. public:
  125. using impl = pixel_view_details::impl<pixel_view_details::tag::reader, Pixel, RawType>;
  126. using impl::impl;
  127. pixel_reader(const pixel_writer<Pixel, RawType> & other);
  128. pixel_reader
  129. (
  130. const pixel_writer<Pixel, RawType> & other,
  131. range2D range
  132. );
  133. };
  134. template<typename Pixel, typename RawType>
  135. pixel_reader(pixel_writer<Pixel, RawType>)
  136. -> pixel_reader<Pixel, RawType>;
  137. template<typename Pixel, typename RawType>
  138. pixel_reader(pixel_writer<Pixel, RawType>, range2D)
  139. -> pixel_reader<Pixel, RawType>;
  140. template<typename Pixel, typename RawType>
  141. pixel_reader(pixel_reader<Pixel, RawType>, range2D)
  142. -> pixel_reader<Pixel, RawType>;
  143. using pixel_reader_variant = pixel_view_variant<pixel_reader>;
  144. using pixel_writer_variant = pixel_view_variant<pixel_writer>;
  145. } // namespace simple::graphical
  146. #endif /* end of include guard */