36 lines
1.4 KiB
C++
36 lines
1.4 KiB
C++
#include "Pixel_Frame.h"
|
|
#include <cstring>
|
|
#include <limits>
|
|
namespace renderive::web {
|
|
namespace {
|
|
void write_u32_le(char* target, std::uint32_t value) {
|
|
target[0] = static_cast<char>(value & 0xffU);
|
|
target[1] = static_cast<char>((value >> 8U) & 0xffU);
|
|
target[2] = static_cast<char>((value >> 16U) & 0xffU);
|
|
target[3] = static_cast<char>((value >> 24U) & 0xffU);
|
|
}
|
|
}
|
|
std::string encode_rgba8_pixel_frame(const std::byte* data, std::uint32_t width, std::uint32_t height, std::uint32_t stride) {
|
|
if (data == nullptr || width == 0 || height == 0 || stride < width * 4U)
|
|
return {};
|
|
const std::size_t row_size = static_cast<std::size_t>(width) * 4U;
|
|
if (static_cast<std::size_t>(height) > (std::numeric_limits<std::size_t>::max() - pixel_frame_header_size) / row_size)
|
|
return {};
|
|
const std::size_t pixel_bytes = row_size * height;
|
|
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, width);
|
|
write_u32_le(frame.data() + 8, height);
|
|
write_u32_le(frame.data() + 12, static_cast<std::uint32_t>(row_size));
|
|
char* output = frame.data() + pixel_frame_header_size;
|
|
for (std::uint32_t y = 0; y < height; ++y) {
|
|
const auto* row = data + static_cast<std::size_t>(y) * stride;
|
|
std::memcpy(output + static_cast<std::size_t>(y) * row_size, row, row_size);
|
|
}
|
|
return frame;
|
|
}
|
|
}
|