#pragma once #include #include #include #include "conv-common.h" namespace kms { /* * Raw Bayer formats */ enum class BayerOrder { RGGB, BGGR, GRBG, GBRG }; template struct Bayer_Layout; // 8-bit bayer formats (uint8_t storage) template struct Bayer_Layout : public FormatLayout>> { static constexpr BayerOrder bayer_order = Order; static constexpr size_t bit_depth = 8; }; // 10-bit bayer formats (uint16_t storage) template struct Bayer_Layout : public FormatLayout, ComponentLayout>> { static constexpr BayerOrder bayer_order = Order; static constexpr size_t bit_depth = 10; }; // 12-bit bayer formats (uint16_t storage) template struct Bayer_Layout : public FormatLayout, ComponentLayout>> { static constexpr BayerOrder bayer_order = Order; static constexpr size_t bit_depth = 12; }; // 16-bit bayer formats (uint16_t storage) template struct Bayer_Layout : public FormatLayout>> { static constexpr BayerOrder bayer_order = Order; static constexpr size_t bit_depth = 16; }; // Convenient aliases for different bit depths template using Bayer8_Layout = Bayer_Layout; template using Bayer10_Layout = Bayer_Layout; template using Bayer12_Layout = Bayer_Layout; template using Bayer16_Layout = Bayer_Layout; // Format-specific type aliases using SRGGB8_Layout = Bayer8_Layout; using SGBRG8_Layout = Bayer8_Layout; using SGRBG8_Layout = Bayer8_Layout; using SBGGR8_Layout = Bayer8_Layout; using SRGGB10_Layout = Bayer10_Layout; using SGBRG10_Layout = Bayer10_Layout; using SGRBG10_Layout = Bayer10_Layout; using SBGGR10_Layout = Bayer10_Layout; using SRGGB12_Layout = Bayer12_Layout; using SGBRG12_Layout = Bayer12_Layout; using SGRBG12_Layout = Bayer12_Layout; using SBGGR12_Layout = Bayer12_Layout; using SRGGB16_Layout = Bayer16_Layout; using SGBRG16_Layout = Bayer16_Layout; using SGRBG16_Layout = Bayer16_Layout; using SBGGR16_Layout = Bayer16_Layout; template class Bayer_Writer { using Plane = typename Layout::template plane<0>; using TStorage = typename Plane::storage_type; static_assert(Layout::num_planes == 1); static_assert(Plane::template component_count() == 1); static constexpr BayerOrder bayer_order = Layout::bayer_order; static constexpr size_t bit_depth = Layout::bit_depth; static constexpr bool has_padding = Plane::template component_count(); static constexpr size_t y_idx = Plane::template find_pos(); static constexpr size_t x_idx = has_padding ? Plane::template find_pos() : 0; static constexpr size_t y_shift = 16 - Plane::template component_size; static constexpr ComponentType get_bayer_component(size_t x, size_t y) { const bool x_even = (x % 2) == 0; const bool y_even = (y % 2) == 0; switch (bayer_order) { case BayerOrder::RGGB: if (y_even && x_even) return ComponentType::R; if (y_even && !x_even) return ComponentType::G; if (!y_even && x_even) return ComponentType::G; return ComponentType::B; case BayerOrder::BGGR: if (y_even && x_even) return ComponentType::B; if (y_even && !x_even) return ComponentType::G; if (!y_even && x_even) return ComponentType::G; return ComponentType::R; case BayerOrder::GRBG: if (y_even && x_even) return ComponentType::G; if (y_even && !x_even) return ComponentType::R; if (!y_even && x_even) return ComponentType::B; return ComponentType::G; case BayerOrder::GBRG: if (y_even && x_even) return ComponentType::G; if (y_even && !x_even) return ComponentType::B; if (!y_even && x_even) return ComponentType::R; return ComponentType::G; } return ComponentType::Y; // fallback } static uint16_t extract_component(const RGB16& pix, ComponentType component) { switch (component) { case ComponentType::R: return pix.r; case ComponentType::G: return pix.g; case ComponentType::B: return pix.b; default: return 0; } } public: static void pack_line(HasIndexOperatorReturning auto&& dst_line, HasIndexOperatorReturning auto&& src_line, size_t num_pixels, size_t y) { for (size_t x = 0; x < num_pixels; x++) { const RGB16& pix = src_line[x]; const ComponentType component = get_bayer_component(x, y); const uint16_t value = extract_component(pix, component); std::array components; if constexpr (has_padding) components[x_idx] = 0; components[y_idx] = value >> y_shift; dst_line[x] = Plane::pack(components); } } static void write_pattern(IFramebuffer& fb, size_t start_y, size_t end_y, auto&& generate_line) { std::vector linebuf(fb.width()); auto view = make_strided_fb_view(fb.map(0), fb.height(), fb.width(), fb.stride(0)); for (size_t y_src = start_y; y_src <= end_y; y_src++) { generate_line(y_src, linebuf); auto dst = md::submdspan(view, y_src, md::full_extent); pack_line(dst, linebuf, fb.width(), y_src); } } }; } // namespace kms