初版网页

This commit is contained in:
2026-08-10 21:05:36 +08:00
parent cfc0849081
commit f50e9f7c1e
19 changed files with 1697 additions and 16 deletions
+68
View File
@@ -0,0 +1,68 @@
#include "Pixel_Frame.h"
#include <algorithm>
#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::uint8_t flatten(std::uint8_t premultiplied, std::uint8_t alpha,
std::uint8_t background) {
return static_cast<std::uint8_t>(
std::min(255U, static_cast<unsigned>(premultiplied) +
(static_cast<unsigned>(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<int>(sizeof(Pixel))) {
return {};
}
const auto width = static_cast<std::size_t>(image.width);
const auto height = static_cast<std::size_t>(image.height);
if (width > (std::numeric_limits<std::size_t>::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<std::uint32_t>(image.width));
write_u32_le(frame.data() + 8, static_cast<std::uint32_t>(image.height));
write_u32_le(frame.data() + 12,
static_cast<std::uint32_t>(image.width * static_cast<int>(sizeof(Pixel))));
auto* output = reinterpret_cast<std::uint8_t*>(frame.data() + pixel_frame_header_size);
for (int y = 0; y < image.height; ++y) {
const auto* row = image.data + static_cast<std::ptrdiff_t>(y) * image.stride;
for (int x = 0; x < image.width; ++x) {
Pixel pixel{};
std::memcpy(&pixel, row + static_cast<std::ptrdiff_t>(x) * sizeof(Pixel), sizeof(pixel));
const auto alpha = static_cast<std::uint8_t>((pixel >> 24U) & 0xffU);
const auto red = static_cast<std::uint8_t>((pixel >> 16U) & 0xffU);
const auto green = static_cast<std::uint8_t>((pixel >> 8U) & 0xffU);
const auto blue = static_cast<std::uint8_t>(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