#include "Pixel_Frame.h" #include #include #include namespace renderive::web { namespace { void write_u32_le(char* target, std::uint32_t value) { target[0] = static_cast(value & 0xffU); target[1] = static_cast((value >> 8U) & 0xffU); target[2] = static_cast((value >> 16U) & 0xffU); target[3] = static_cast((value >> 24U) & 0xffU); } std::uint8_t flatten(std::uint8_t premultiplied, std::uint8_t alpha, std::uint8_t background) { return static_cast( std::min(255U, static_cast(premultiplied) + (static_cast(background) * (255U - alpha) + 127U) / 255U)); } } // namespace std::string encode_pixel_frame(Image_View image, Color background) { if (image.empty() || image.format != Pixel_Format::Premultiplied_32 || image.stride < image.width * static_cast(sizeof(Pixel))) { return {}; } const auto width = static_cast(image.width); const auto height = static_cast(image.height); if (width > (std::numeric_limits::max() - pixel_frame_header_size) / (height * sizeof(Pixel))) { return {}; } const std::size_t pixel_bytes = width * height * sizeof(Pixel); std::string frame(pixel_frame_header_size + pixel_bytes, '\0'); frame[0] = 'R'; frame[1] = 'V'; frame[2] = 'P'; frame[3] = '1'; write_u32_le(frame.data() + 4, static_cast(image.width)); write_u32_le(frame.data() + 8, static_cast(image.height)); write_u32_le(frame.data() + 12, static_cast(image.width * static_cast(sizeof(Pixel)))); auto* output = reinterpret_cast(frame.data() + pixel_frame_header_size); for (int y = 0; y < image.height; ++y) { const auto* row = image.data + static_cast(y) * image.stride; for (int x = 0; x < image.width; ++x) { Pixel pixel{}; std::memcpy(&pixel, row + static_cast(x) * sizeof(Pixel), sizeof(pixel)); const auto alpha = static_cast((pixel >> 24U) & 0xffU); const auto red = static_cast((pixel >> 16U) & 0xffU); const auto green = static_cast((pixel >> 8U) & 0xffU); const auto blue = static_cast(pixel & 0xffU); *output++ = flatten(red, alpha, background.r); *output++ = flatten(green, alpha, background.g); *output++ = flatten(blue, alpha, background.b); *output++ = 255; } } return frame; } } // namespace renderive::web